找出数组的第k大和

Posted 929code

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了找出数组的第k大和相关的知识,希望对你有一定的参考价值。

给你一个整数数组 nums 和一个正整数 k 。你可以选择数组的任一子序列并且对其全部元素求和。
数组的第 k 大和 定义为:可以获得的第 k 个 最大 子序列和(子序列和允许出现重复)
返回数组的第 k 大和

1. 转化问题 + 大根堆

class Solution 
public:
    long long kSum(vector<int> &nums, int k) 
        long sum = 0L;
        for (int &x : nums) //对正数求和,同时将负数变为正数
            if (x >= 0) sum += x;
            else x = -x;
        sort(nums.begin(), nums.end()); //排序
        //原问题转化成为从原数组中选择元素减去
        priority_queue<pair<long, int>> pq; //大根堆,存储扩张时的状态,类似深度优先搜索
        pq.emplace(sum, 0); //第一大
        while (--k)  //循环运行k-1次
            auto[sum, i] = pq.top(); //当前最大值和当前待操作下标
            pq.pop();
            if (i < nums.size()) 
                //扩张时两种选择,第一种减去当前操作数,第二种跳过当前操作数
                //但是由于涉及到大根堆优先级,所以不能直接跳过,而是后面补回来
                pq.emplace(sum - nums[i], i + 1); // 保留 nums[i-1]
                if (i) pq.emplace(sum - nums[i] + nums[i - 1], i + 1); // 不保留 nums[i-1],把之前减去的加回来
            
        
        return pq.top().first;
    
;

2. 二分

class Solution 
public:
    long long kSum(vector<int> &nums, int k) 
        //预处理
        long sum = 0L;
        for (int &x : nums) 
            if (x >= 0) sum += x;
            else x = -x;
        
        sort(nums.begin(), nums.end());
        
        --k;//
        auto check = [&](long limit) -> bool 
            int cnt = 0;
            //暴搜所有小于等于mid的序列和个数
            function<void(int, long)> f = [&](int i, long s) 
                if (i == nums.size() || cnt >= k || s + nums[i] > limit) return; //边界条件
                ++cnt; //因为后面都可以不选,满足条件序列个数加一
                f(i + 1, s + nums[i]); // 选
                f(i + 1, s); // 不选
            ;
            f(0, 0L);
            return cnt >= k;
        ;

        //求最大的结果,从数组中减去最小的序列,即有k个序列和满足值即可
        long left = 0L, right = accumulate(nums.begin(), nums.end(), 0L);
        while (left < right) 
            long mid = (left + right) / 2; //累计和
            if (check(mid)) right = mid; //小于等于累计和的序列个数大于等于阈值
            else left = mid + 1; //小于阈值,不满足条件
        
        return sum - left; //减去对应累计和
    
;

Leetcode刷题100天—5855. 找出数组中的第 K 大整数(优先队列)—day22

前言:

作者:神的孩子在歌唱

大家好,我叫运智

5855. 找出数组中的第 K 大整数

难度中等1收藏分享切换为英文接收动态反馈

给你一个字符串数组 nums 和一个整数 knums 中的每个字符串都表示一个不含前导零的整数。

返回 nums 中表示第 k 大整数的字符串。

**注意:**重复的数字在统计时会视为不同元素考虑。例如,如果 nums["1","2","2"],那么 "2" 是最大的整数,"2" 是第二大的整数,"1" 是第三大的整数。

示例 1:

输入:nums = ["3","6","7","10"], k = 4
输出:"3"
解释:
nums 中的数字按非递减顺序排列为 ["3","6","7","10"]
其中第 4 大整数是 "3"

示例 2:

输入:nums = ["2","21","12","1"], k = 3
输出:"2"
解释:
nums 中的数字按非递减顺序排列为 ["1","2","12","21"]
其中第 3 大整数是 "2"

示例 3:

输入:nums = ["0","0"], k = 2
输出:"0"
解释:
nums 中的数字按非递减顺序排列为 ["0","0"]
其中第 2 大整数是 "0"

提示:

  • 1 <= k <= nums.length <= 104
  • 1 <= nums[i].length <= 100
  • nums[i] 仅由数字组成
  • nums[i] 不含任何前导零
package 优先队列;

import java.util.Arrays;

public class _5855_找出数组中的第K大整数 {
    public String kthLargestNumber(String[] nums, int k) {
//自定义排序
    	Arrays.sort(nums, ((o1, o2) -> {
            if (o1.length() > o2.length())
                return -1;
            else if (o1.length() < o2.length())
                return 1;
            else
                return o2.compareTo(o1);
        }));
        return String.valueOf(nums[k - 1]);
    }
}

本人csdn博客:https://blog.csdn.net/weixin_46654114

转载说明:跟我说明,务必注明来源,附带本人博客连接。

以上是关于找出数组的第k大和的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode刷题100天—5855. 找出数组中的第 K 大整数(优先队列)—day22

Leetcode刷题100天—5855. 找出数组中的第 K 大整数(优先队列)—day22

Leetcode——找出数组中的第 K 大整数(字符串中数字排序)

LeetCode 5855. 找出数组中的第 K 大整数(自定义排序函数)

2021-06-01:K个逆序对数组。给出两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数。逆序对的定义如下:对于数组的第i个和第 j个元素,如果满

面试官:找出数组中的第 6 大元素,我直接懵逼了。。