【算法】堆

堆(优先队列)

思考:感觉能排序基本就不要用堆,没有排序快

speed up repeated minimum computationns so that each computation takes logarithmic rather than linear time

堆是一种特别的二叉树,满足以下条件的二叉树,可以称之为堆:

  1. 完全二叉树 从上到下,从左到右依次被填满
  2. 每一个节点的值都必须大于等于或者小于等于其孩子节点的值。

特点:插入和删除元素 时间复杂度为 O(logN);获取最大值/最小值 时间复杂度为 O(1)

堆 有两种类型:最大堆最小堆

默认的Comparator是升序,所以建出来的是最小堆

1

  1. 1337. 矩阵中战斗力最弱的 K 行 先按战斗力排,一样再看行数谁靠后 建堆(最小堆)
  2. 703. 数据流中的第 K 大元素 建堆(最小堆),取数(最小的数放最上面,让堆保持只有k个数,剩余的可以直接舍弃)
  3. 1046. 最后一块石头的重量 建最大堆
  4. 剑指 Offer 40. 最小的k个数 但是排序比建堆运行快一点
  5. 2099. 找到和最大的长度为 K 的子序列 我用了两个堆,先按照大小将k个数存储到最小堆中,再按照数组中的位置将前面堆中的元素放到新的最小堆中。新的最小堆中的元素即为答案

代码示例

703. 数据流中的第 K 大元素

public int[] kWeakestRows(int[][] mat, int k) {
    int m = mat.length, n = mat[0].length;
    List<int[]> power = new ArrayList<>();
    // 用二分法找到每一行的最后一个1的位置
    // 如果最后一个1的位置为pos,则该行军人数为pos + 1
    for(int i = 0; i < m; i++) {
        int left = 0, right = n - 1, pos = -1;
        while(left <= right) {
            int mid = (left + right) >> 1;
            if(mat[i][mid] == 1) {
                pos = mid;
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        power.add(new int[]{pos + 1, i});
    }

    PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
        public int compare(int[] pair1, int[] pair2) {
            if(pair1[0] != pair2[0]) {
                return pair1[0] - pair2[0];
            } else {
                return pair1[1] - pair2[1];
            }
        }
    } );

    for(int[] pair : power) {
        pq.offer(pair);
    }

    int[] ans = new int[k];
    for(int i = 0; i < k; i++) {
        ans[i] = pq.poll()[1];
    }

    return ans;
}

1046. 最后一块石头的重量

public int lastStoneWeight(int[] stones) {
    // 匿名类
    PriorityQueue<Integer> pq= new PriorityQueue<Integer>(new Comparator<Integer>() {
        public int compare(Integer o1, Integer o2) {
            return o2 - o1;
        }
    });

    // Lambda表达式
    PriorityQueue<Integer> pq= new PriorityQueue<Integer>((o1, o2) -> (o2 - o1));

    for(int stone : stones) {
        pq.offer(stone);
    }

    while(pq.size() != 1 && pq.size() != 0) {
        int y = pq.poll();
        int x = pq.poll();
        if(x != y) {
            pq.offer(y - x);
        }
    }

    return pq.isEmpty() ? 0 : pq.poll();
}
posted @   sleepyhermit  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示