矩阵中战斗力最弱的K行

1337. 矩阵中战斗力最弱的 K 行 题解 - 力扣(LeetCode)

目录

 思路

代码

 运行结果


 思路

1. 为了便于比较,把每行的士兵个数和行标关联起来形成pair,pair.first表示士兵个数,pair.second表示行标

2. 首先选取前k行做成一个固定大小的最大堆

3. 然后遍历剩余的行,如果战斗力比最大堆堆顶元素弱,那么就替换掉最大堆堆顶元素,然后调整堆,遍历完后最大堆中的k个元素即为最弱的k行

4. 每次从堆顶抽取最大元素,倒序放入最终容器,并调整堆,如此执行k次即可

代码

#define top 1
#define NOP 0
class Solution {
    int k;
    typedef pair<int, int> cor;
    vector<cor> maxHeap;
public:
    vector<int> kWeakestRows(vector<vector<int>>& mat, int K) {
        k = K;
        build_heap(mat);

        int size = mat.size();
        for (int idx = K; idx != size; ++idx) {
            add(maxHeap, num_of_solders(mat[idx]), idx);
        }

        vector<int> ans(K);
        for (int i = K - 1; i != -1; --i) {
            ans[i] = maxHeap[top].second;
            sink(make_pair(-1, 0), top);
        }
        return ans;
    }

    void build_heap(vector<vector<int>>& mat) {
        maxHeap.emplace_back(NULL, NULL);
        for (int idx = 0; idx != k; ++idx) {
            maxHeap.emplace_back(num_of_solders(mat[idx]), idx);
        }
        for (int pos = k / 2; pos; --pos) {
            sink(maxHeap[pos], pos);
        }
    }

    void add(vector<cor>& maxHeap, int num, int idx) {
        cor intruder = make_pair(num, idx);
        compare(intruder, maxHeap[top]) ? NOP : sink(intruder, top);
    }

    int sink(cor pebble, int pos) {
        int bubble;
        while ((bubble = pos * 2) <= k) {
            bubble != k && compare(maxHeap[bubble + 1], maxHeap[bubble]) ? ++bubble : 0;
            if (compare(pebble, maxHeap[bubble])) break;
            maxHeap[pos] = maxHeap[bubble];
            pos = bubble;
        }
        maxHeap[pos] = pebble;
        return 0;
    }

    int compare(cor& intruder, cor& defender) {
        return intruder.first > defender.first ||
            intruder.first == defender.first && intruder.second > defender.second ?
            1 : 0;
    }

    int num_of_solders(vector<int>& row) {
        int start = 0, end = row.size();
        int separatrix = end / 2;
        while(1) {
            if (row[separatrix]) {
                if (separatrix + 1 == end || !row[separatrix + 1]) return separatrix + 1;
                start = separatrix + 1;
            }
            else {
                if (separatrix == start || row[separatrix - 1]) return separatrix;
                end = separatrix;
            }
            separatrix = start + (end - start) / 2;
        }
    }

};

 运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值