【Leetcode】优先队列(PriorityQueue)问题解析

news/2024/5/18 22:12:15 标签: leetcode, 算法, 优先队列, PriorityQueue,

优先队列PriorityQueue对应的是一种常用的数据结构。

文章目录

      • 优先队列PriorityQueue
      • 23. 合并K个升序链表
        • 1. 题目描述
        • 2. 思路分析
        • 3. 参考代码
      • 215. 数组中的第K个最大元素
        • 1. 题目描述
        • 2. 思路分析
        • 3. 参考代码
      • 1753. 移除石子的最大得分
        • 1. 题目描述
        • 2. 思路分析
        • 3. 参考代码
      • LCP 30. 魔塔游戏
        • 1. 题目描述
        • 2. 思路分析
        • 3. 参考代码
      • 1705. 吃苹果的最大数目
        • 1. 题目描述
        • 2. 思路分析
        • 3. 参考代码
      • 778. 水位上升的泳池中游泳
        • 1. 题目描述
        • 2. 思路分析
        • 3. 参考代码

PriorityQueue_3">优先队列PriorityQueue

1. 简介

Java PriorityQueue 实现了 Queue 接口,不允许放入 null 元素;其通过实现,具体说是通过完全二叉树(complete binary tree)实现的小顶(任意一个非叶子节点的权值,都不大于其左右子节点的权值),也就意味着可以通过数组来作为PriorityQueue 的底层实现,数组初始大小为11;也可以用一棵完全二叉树表示。

2. java内置优先队列的API

PriorityQueue queue = new PriorityQueue(new Comparator<Integer>() {
	  @Override
	    public int compare(Integer o1, Integer o2) {
	        return o1 - o2;
	    }
	});

Lambda表达式写法(推荐使用)

PriorityQueue<Integer> queue = new PriorityQueue<>((o1 , o2) -> o1 - o2); // 小根
PriorityQueue<Integer> queue = new PriorityQueue<>((o1 , o2) -> o2 - o1); // 大根

23. 合并K个升序链表

1. 题目描述

leetcode题目链接:23. 合并K个升序链表
在这里插入图片描述

2. 思路分析

将链表存入优先队列中,使用优先队列来选择最小元素,先把k个链表加入到优先队列中,然后依次从队列中取出链表,把链表的节点插入小根中。

3. 参考代码

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        // 小根
        PriorityQueue<ListNode> queue = new PriorityQueue<>((o1, o2) -> (o1.val - o2.val));
        for (ListNode list : lists) {
            if (list != null) {
                queue.offer(list);
            }
        }
        ListNode dummy = new ListNode(-1);  // 头结点
        ListNode cur = dummy;
        while (!queue.isEmpty()) {
            ListNode head = queue.poll();
            cur.next = head;
            if (head.next != null) {
                queue.offer(head.next);
            }
            cur = cur.next;
        }
        return dummy.next;
    }
}

215. 数组中的第K个最大元素

1. 题目描述

leetcode题目链接:215. 数组中的第K个最大元素
在这里插入图片描述

2. 思路分析

优先队列:小根存储元素,判断当中元素多于k个时,删除顶元素。 最后顶元素即为第k个最大元素。

3. 参考代码

class Solution {
    public int findKthLargest(int[] nums, int k) {
        // 小根
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for (int num : nums) {
            queue.offer(num);
            // 中元素多于k个时,删除顶元素
            if (queue.size() > k) {
                queue.poll();
            }
        }
        return queue.peek();  // 顶元素即为第k个最大元素
    }
}

1753. 移除石子的最大得分

1. 题目描述

leetcode题目链接:1753. 移除石子的最大得分
在这里插入图片描述

2. 思路分析

方法一:排序

当排序后的第一个数或者第二个数大于0的时候,将第一个数和第二个数分别减1,得分加1,重新对数组进行排序。

方法二:优先队列

大根,第一个poll()就是最大的,第二个poll()的就是中间的,判断当中间的值不等于0,分数加1,再把最大值和中间值各自减一加入大根

3. 参考代码

方法一:排序

class Solution {
    public int maximumScore(int a, int b, int c) {
        // 排序
        int[] nums = new int[]{a, b, c};
        Arrays.sort(nums);
        int res = 0;
        while (nums[0] > 0 || nums[1] > 0) {
            nums[1]--;
            nums[2]--;
            res++;
            Arrays.sort(nums);
        }
        return res;
    }
}

方法二:优先队列

class Solution {
    public int maximumScore(int a, int b, int c) {
        // 大根
        PriorityQueue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2 - o1);
        queue.offer(a);
        queue.offer(b);
        queue.offer(c);
        int res = 0;
        while(true) {
            int max = queue.poll();
            int mid = queue.poll();
            if (mid == 0) break;
            res++;
            queue.offer(mid - 1);
            queue.offer(max - 1);
        }
        return res;
    }
}

LCP 30. 魔塔游戏

1. 题目描述

leetcode题目链接:LCP 30. 魔塔游戏
在这里插入图片描述

2. 思路分析

贪心算法优先队列,当血不够减时,把扣的最多的血加回来,再把扣的最多的血调整数组末尾。优先队列用来存储扣的血,小根,每次输出的都是扣的最多的血。

3. 参考代码

class Solution {
    public int magicTower(int[] nums) {
        // 贪心算法优先队列,每次不够用的时候,将负的最小值调整到序列末尾
        int sum = Arrays.stream(nums).sum();
        sum = sum + 1;
        if (sum < 1) return -1;
        long blood = 1;  // 防止溢出
        int count = 0;
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for (int num : nums) {
            blood += num;
            if (num < 0) queue.offer(num);
            if (blood < 1) {
                while (blood < 1 && !queue.isEmpty()) {
                    blood -= queue.poll();  // 加上减去的最小值,将最小值调整到末尾
                    count++;
                }
            }
        }
        return count;
    }
}

1705. 吃苹果的最大数目

1. 题目描述

leetcode题目链接:1705. 吃苹果的最大数目
在这里插入图片描述

2. 思路分析

优先队列,按第i天的苹果可以存储到的天数和第i天长出的苹果个数,构建小根。如果时间到了,且没有处在保质期的苹果,则break。然后移除超过保质期的苹果,最后吃苹果。

3. 参考代码

class Solution {
    public int eatenApples(int[] apples, int[] days) {
        // 优先队列,按第i天的苹果可以存储到的天数和第i天长出的苹果个数,构建小根
        PriorityQueue<int[]> queue = new PriorityQueue<>((o1, o2) -> o1[0] - o2[0]);
        int count = 0, day = 0;
        while (true) {
            if (day < apples.length) {
                queue.offer(new int[]{days[day] + day, apples[day]});
            } else if (day >= apples.length && queue.isEmpty()) {
                break;  // 时间到了,且没有处在保质期的苹果
            }
            // 移除腐烂苹果
            while (!queue.isEmpty() && (queue.peek()[0] <= day || queue.peek()[1] == 0)) {
                queue.poll();
            }
            // 吃苹果
            if (!queue.isEmpty()) {
                count++;
                queue.peek()[1]--;
            }
            // 天数+1
            day++;
        }
        return count;
    }
}

778. 水位上升的泳池中游泳

1. 题目描述

leetcode题目链接:778. 水位上升的泳池中游泳
在这里插入图片描述
在这里插入图片描述

2. 思路分析

优先队列+BFS,从起点开始bfs扩散,看需要几步到达终点,使用优先队列选择最小的高度,res = Math.max(res, 路径中每个位置的高度)。

3. 参考代码

class Solution {
    public int swimInWater(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        boolean[][] visited = new boolean[m][n];
        int res = 0;
        int[][] dirs = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
        // 优先队列每次拿出高度最小的元素
        PriorityQueue<int[]> queue = new PriorityQueue<>((a, b) -> grid[a[0]][a[1]] - grid[b[0]][b[1]]);
        queue.offer(new int[]{0, 0});  // 存储索引
        visited[0][0] = true;
        while (!queue.isEmpty()) {
            int[] index = queue.poll();
            res = Math.max(res, grid[index[0]][index[1]]);
            if (index[0] == m - 1 && index[1] == n - 1) {
                return res;
            }
            for (int[] dir : dirs) {
                int x = index[0] + dir[0];
                int y = index[1] + dir[1];
                if (x < 0 || y < 0 || x >= m || y >= n || visited[x][y]) {
                    continue;
                }
                queue.offer(new int[]{x, y});
                visited[x][y] = true;
            }
        }
        return -1;
    }
}

http://www.niftyadmin.cn/n/1727630.html

相关文章

pg数据库在Linux中安装失败,提示the database cluster initialisation failed

前几天客户现场安装pg数据库死活安装不成功&#xff0c;当时测的时候从来没出现过这种情况&#xff0c;几个人折腾了半天也没整好&#xff0c;最后竟然是更改了locale【zh_CN.utf8】的值&#xff0c;而不是选择默认值&#xff0c;结果奇迹般的安装成功了&#xff0c;这个是选择…

PG数据库更改端口后psql等命令无法使用的问题

今天尝试在Linux中安装pg数据库时更改了端口&#xff0c;结果安装完成后使用psql命令会提示 psql.bin: could not connect to server: 没有那个文件或目录 Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.PGS…

pg数据库的配置文件 /tmp/postgres-reg.ini

pg数据库在Linux系统中安装完成后&#xff0c;会有一个默认路径的配置文件/tmp/postgres-reg.ini 它里边保存着pg数据库的各种信息&#xff0c;包括安装路径、data数据路径以及端口port等&#xff0c;想得到pg数据库的安装信息的朋友可以读取该文件来获取。

jxcore源码编译安装

说明文档&#xff1a; https://github.com/jxcore/jxcore/blob/master/doc/HOW_TO_COMPILE.md

webpack-externals过滤文件

/* * 研究使用webpack也有一段时间了&#xff0c;现在终于有了大概的认识和了解&#xff0c;下边是一个简单的例子&#xff0c;不懂的朋友可以照猫画虎&#xff0c;哈哈 * */ var fs require(fs); var path require(path); var nodeModules {}; //过滤node_modules中的所有模…

postgresql数据库--psql、pg_dump命令带密码执行sql语句

pg_dump: pg_dump -a -t tbl_test "host127.0.0.1 hostaddr127.0.0.1 port5432 userpostgres password123456 dbnamepostgres" > /userdir/tbl_data -a 参数是表示只导出数据&#xff0c;其他的额外信息不需要&#xff0c;该参数也可去掉 psql: psql --comman…

js Date()函数常用方法

代码&#xff1a; var date new Date(); var a date.getDate(); console.log("getDate:"a); var b date.getDay(); console.log("getDay:"b); var c date.getFullYear(); console.log("getFullYear:"c); var d date.getHours(); console.l…

微服务实战系列之SpringCloud Alibaba学习(六)

微服务实战系列之SpringCloud Alibaba&#xff1a; 微服务实战系列之SpringCloud Alibaba学习&#xff08;一&#xff09;微服务实战系列之SpringCloud Alibaba学习&#xff08;二&#xff09;微服务实战系列之SpringCloud Alibaba学习&#xff08;三&#xff09;微服务实战系…