力扣每日一题 找出数组的第 K 大和 小根堆 逆向思维(TODO:二分+暴搜)

Problem: 2386. 找出数组的第 K 大和

文章目录

  • 思路
  • 复杂度
  • [💖 小根堆](#💖 小根堆)
  • [💖 TODO:二分 + 暴搜](#💖 TODO:二分 + 暴搜)

思路

👨‍🏫 灵神题解


复杂度

时间复杂度:

添加时间复杂度, 示例: O ( n ) O(n) O(n)

空间复杂度:

添加空间复杂度, 示例: O ( n ) O(n) O(n)

💖 小根堆

Java 复制代码
class Solution {
	class Pair
	{
		long sum;
		int idx;

		public Pair(long x, int y)
		{
			super();
			this.sum = x;
			this.idx = y;
		}
	}

	public long kSum(int[] nums, int k)
	{
		long sum = 0;
		int n = nums.length;
		for (int i = 0; i < n; i++)
		{
			if (nums[i] >= 0)
				sum += nums[i];
			else
				nums[i] = -nums[i];
		}
		Arrays.sort(nums);
		PriorityQueue<Pair> heap = new PriorityQueue<>((a, b) -> Long.compare(a.sum, b.sum));
		heap.offer(new Pair(0L, 0));// 空子序列
//		一个不选也是一种情况
		while (--k > 0)// 注意:--k 比 k-- 要少一次循环
		{
			Pair p = heap.poll();
			long s = p.sum;
//			System.out.print(s + " "); //调试输出
			int i = p.idx;
			if (i < n)
			{
//				在子序列末尾添加 nums[i]
				heap.offer(new Pair(s + nums[i], i + 1));// 下一个要添加的元素下标为 i+1
				if (i > 0)// 替换子序列末尾元素为 nums[i]
					heap.offer(new Pair(s + nums[i] - nums[i - 1], i + 1));
			}
		}
//		heap.peek().sum 是第k小
//		sum 是第 1 大
		return sum - heap.peek().sum;
	}

}

💖 TODO:二分 + 暴搜

java 复制代码
class Solution {
    public long kSum(int[] nums, int k) {
        long sum = 0, right = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] >= 0) {
                sum += nums[i];
            } else {
                nums[i] = -nums[i];
            }
            right += nums[i];
        }
        Arrays.sort(nums);

        long left = -1;
        while (left + 1 < right) { // 开区间二分,原理见【前置知识】
            long mid = (left + right) / 2;
            cnt = k - 1; // 空子序列算一个
            dfs(0, mid, nums);
            if (cnt == 0) { // 找到 k 个元素和不超过 mid 的子序列
                right = mid;
            } else {
                left = mid;
            }
        }
        return sum - right;
    }

    private int cnt;

    // 反向递归,增加改成减少,这样可以少传一些参数
    private void dfs(int i, long s, int[] nums) {
        if (cnt == 0 || i == nums.length || s < nums[i]) {
            return;
        }
        cnt--;
        dfs(i + 1, s - nums[i], nums); // 选
        dfs(i + 1, s, nums); // 不选
    }
}

// 作者:灵茶山艾府
相关推荐
ambition202423 分钟前
深度优先搜索(DFS)与回溯算法详解:以全排列问题为例
算法·深度优先
Omics Pro3 分钟前
马普所:生命蛋白质宇宙聚类
数据库·人工智能·算法·机器学习·数据挖掘·aigc·聚类
汀、人工智能4 分钟前
[特殊字符] 第106课:旋转图像
数据结构·算法·矩阵·数据库架构·数组·旋转图像
ulias2128 分钟前
leetcode热题 - 2
算法·leetcode·职场和发展
Ivanqhz9 分钟前
SMT(Satisfiability Modulo Theories,基于模理论的可满足性)
人工智能·算法·机器学习
游乐码16 分钟前
C#Dicitionary
算法·c#
华清远见IT开放实验室21 分钟前
AI 算法核心知识清单(深度实战版1)
人工智能·python·深度学习·学习·算法·机器学习·ai
牧瀬クリスだ21 分钟前
七大排序一次满足
数据结构·算法·排序算法
liu****22 分钟前
第15届省赛蓝桥杯大赛C/C++大学B组
开发语言·数据结构·c++·算法·蓝桥杯·acm
无缘之缘34 分钟前
蓝桥杯手把手教你备战(C/C++ B组)(最全面!最贴心!适合小白!)
c语言·c++·算法·蓝桥杯