首页 > 其他分享 >有序矩阵中的第 k 个最小数组和-小顶堆法

有序矩阵中的第 k 个最小数组和-小顶堆法

时间:2023-05-28 21:59:25浏览次数:52  
标签:堆法 int sum 矩阵 vector entry 小顶 size mat

有序矩阵中的第k个最小数组和

题目描述

image

方法一

从上到下遍历矩阵的所有行,假设计算出了前 \(i−1\) 行形成的前 \(k\) 个最小数组和(记作 \(sum\) ),遍历到第 \(i\) 行时,把 \(sum\) 与第 \(i\) 行的数两两相加,然后只保留其中最小的 \(k\) 个数,作为新的 \(sum\) ,然后继续遍历矩阵的下一行,重复该过程直至结束。
代码如下:

class Solution {
public:
    int kthSmallest(vector<vector<int>> &mat, int k) {
        vector<int> a = {0};
        for (auto &row: mat) {
            vector<int> b;
            for (int x: a)
                for (int y: row)
                    b.push_back(x + y);
            sort(b.begin(), b.end());
            // 保留最小的 k 个
	    if (b.size() > k) 
            	b.resize(k);
            a = move(b);
        }
        return a.back();
    }
};

调用std::move函数,该函数是将一个左值转换为右值,之后便是利用移动构造函数进行拷贝,能够提高效率。
时间复杂度为 O(mnklogk), m是矩阵行数,n是列数。

方法二

image
其中,\(l_g\) 个序列的首项为: $$f[0]+g[0],f[0]+g[1],...,f[0]+g[l_g-1]$$
将首项存入堆中之后,可以访问到它的首个元素,也就是最小的元素。此后,将该元素的下一项存入堆中。如此反复k次,即可求得答案。通过阅读官方题解我们也可以发现,方法一的暴力法效率不高的原因在于遍历了矩阵的每一行,而事实上融合优先队列,只需要k次处理即可。
代码如下:

class Solution {
public:
    int kthSmallest(vector<vector<int>>& mat, int k) {
        int m = mat.size();
        vector<int> prev = mat[0];
        for (int i = 1; i < m; ++i) 
        {
            //移动构造函数,提高性能
            prev = move(merge(prev, mat[i], k));
        }
        return prev[k - 1];
    }

    vector<int> merge(const vector<int>& f, const vector<int>& g, int k) {
        if (g.size() > f.size()) {
            return merge(g, f, k);
        }

        priority_queue<Entry> q;
        for (int i = 0; i < g.size(); ++i) {
            q.emplace(0, i, f[0] + g[i]);
        }

        vector<int> ans;
        while (k && !q.empty()) {
            Entry entry = q.top();
            q.pop();
            ans.push_back(entry.sum);
            if (entry.i + 1 < f.size()) 
            {
                q.emplace(entry.i + 1, entry.j, f[entry.i + 1] + g[entry.j]);
            }
            --k;
        }

        return ans;
    }

private:
    struct Entry {
        int i, j, sum;
        Entry(int _i, int _j, int _sum): i(_i), j(_j), sum(_sum) {}
        //与sort的cmp不同,operator<为真,就把sum所在的对象排在后边
        bool operator< (const Entry& that) const {
            return sum > that.sum;
        }
    };
};

image

标签:堆法,int,sum,矩阵,vector,entry,小顶,size,mat
From: https://www.cnblogs.com/parallel-138/p/17438921.html

相关文章

  • 有序矩阵中的第 k 个最小数组和
    1.暴力记录前k个classSolution{public:intkthSmallest(vector<vector<int>>&mat,intk){vector<int>pre(k,0);//存储前k个最小的和intcur[mat[0].size()*k];//存储intsize=1;//用于记录pre当前大小for(auto&r......
  • 深入分析:矩阵梯度类实例研究
    写在前面本文主要用于围绕矩阵类求梯度等问题进行证明与分析,由于笔者的数理基础浅薄,下面的证明过程若存在错误,欢迎评论指正。矩阵梯度的通用方法:先将矩阵写成微分形式,\(df=tr(GdX)\),然后得到$\nablaf=G^T$案例1\(\begin{array}{ll}\min_{U}&\dfrac{1}{2}\left\|\boldsymbol{......
  • 算法刷题记录:回行矩阵(未AC,TLE了)
    题目链接:https://ac.nowcoder.com/acm/contest/19306/1026题目分析这种题,画个图,模拟就对啦。TLE代码#include<iostream>usingnamespacestd;intn,cnt;intw[25][25];intmain(){cin>>n;//构建框架intdx=1,dy=1;while(1)......
  • #295. 「BJWC2010」矩阵距离 题解 2021-09-23 21:42:32
    #295.「BJWC2010」矩阵距离又是一道需要真正思考了才可以做出来的水题。题目描述给出一个N*M的01矩阵,输出每个0到离这个点最近的1的距离。思考历程暴力由于$N\le10^3$如果在赛场上出现这个题,我们优先考虑暴力。暴力也是很简单,从每个为0的点出发bfs找到与最近的......
  • 矩阵快速幂总结
    例题:LuoguP3977[TJOI2015]棋盘朴素做法明显可以进行状压DP,用\(f_{i,j}\)表示在第\(i\)行时下一行状态为\(j\)的方案数。但是这样复杂度是\(\Omicron(n2^{2m})\)的,即便预处理优化也只能达到\(\Omicron(nm2^m)\),因此需要对算法进行优化。优化思路+方法发现每次从......
  • 2022-2023 春学期 矩阵与数值分析 C4 逐次逼近法
    2022-2023春学期矩阵与数值分析C4逐次逼近法原文C4逐次逼近法4.1解线性方程组的迭代法简单迭代法迭代格式可将线性方程组变形\[Ax=b\Leftrightarrowx=Bx+f\]其中B为迭代矩阵,且\[B\inR^{n\timesn},f\inR^n,x\inR^n\]迭代法:称使用\[x^{(k+1)}=Bx^{k}+f\;(k=......
  • Numpy_矩阵的multiply_python的属性以及类特性_装饰器——@property_@classmethod_@st
    Python类中有三个常用的装饰器分别是@property(使一个方法可以被当成属性调用,常用于直接返回某一不想被修改的属性)@classmethod(将一个方法定义为类方法,其中第一个参数要修改为cls,使得该方法可以不用实例化即可被调用)@staticmethod(静态方法,类似于类方法,也可以不用实例化,......
  • es笔记七之聚合操作之桶聚合和矩阵聚合
    本文首发于公众号:Hunter后端原文链接:es笔记七之聚合操作之桶聚合和矩阵聚合桶(bucket)聚合并不像指标(metric)聚合一样在字段上计算,而是会创建数据的桶,我们可以理解为分组,根据某个字段进行分组,将符合条件的数据分到同一个组里。桶聚合可以有子聚合,意思就是在分组之后,可以在每......
  • NumPy_矩阵的八种运算以及变换矩阵
    概念numpy下的linalg=linear+algebra01.数学概念vector向量array:数组matrix:矩阵标量(数量)物理定义:只有大小,没有方向的量n个有次序的数a_{1},a_{2},····,a_{n}所组成的数组称为n维向量--行向量和列向量数组,是有序的元素序列m×n个数aij(i=1,2......
  • 求矩阵的值_为多表代换密码解密做准备
    介绍:先输入n,然后输入n*n矩阵,最后输出矩阵的值。#include<bits/stdc++.h>usingnamespacestd;floatresult;intA[1010][1010];floatAA[1010][1010];intn;voidSwap(float*a,float*b){for(inti=1;i<=n;++i){floattemp=a[i];......