【每日一题Day149】LC2389和有限的最长子序列 | 贪心+前缀和+二分查找

简介: 【每日一题Day149】LC2389和有限的最长子序列 | 贪心+前缀和+二分查找

和有限的最长子序列【LC2389】

给你一个长度为 n 的整数数组 nums ,和一个长度为 m 的整数数组 queries

返回一个长度为 m 的数组 answer其中 answer[i]nums 中 元素之和小于等于 queries[i]子序列最大 长度 。

子序列 是由一个数组删除某些元素(也可以不删除)但不改变剩余元素顺序得到的一个数组。

真的是简单题?

  • 思路:贪心+前缀和+二分查找
  • 由于要求寻找小于目标值的子序列的最大长度【全局最优】,因此我们可以优先选择较小的数字【局部最优】
  • 又由于要求寻找的是子序列,数组元素可以改变顺序,因此可以将数组从小到大排序
  • 然后求出数组元素的前缀和数组,在前缀和数组中搜索小于目标值的最大值对应的下标,即为小于目标值的最长子序列长度

实现

由于前缀和数组可能存在越界,因此可以先记录queries数组的最大值,当前缀和超过该值时,退出循环,记录此时的下标,即为二分查找的右边界

class Solution {
    public int[] answerQueries(int[] nums, int[] queries) {
        int m = queries.length, n = nums.length;
        int[] ans = new int[m];        
        Arrays.sort(nums);
        int maxQ = 0;
        for (int i = 0; i < m; i++){
            maxQ = Math.max(maxQ, queries[i]);
        }
        int[] sum = new int[n + 1];
        int r = n;
        for (int i = 0; i < n; i++){
            if (nums[i] + sum[i] > maxQ) {
                r = i;
                break;
            }
            sum[i + 1] = nums[i] + sum[i];
        }
        for (int i = 0; i < m; i++){
            ans[i] = binarySearch(sum, queries[i], r);
        }
        return ans;
    }
    public int binarySearch(int[] sum, int target, int r){
        int l = 1;
        while (l <= r){
            int mid = (l + r) >> 1;
            if (sum[mid] <= target){
                l = mid + 1;
            }else{
                r = mid - 1;
            }
        }
        return l - 1;
    }
}

image.png

目录
相关文章
|
1月前
【每日一题Day342】LC2578最小和分割 | 贪心
【每日一题Day342】LC2578最小和分割 | 贪心
25 0
|
1月前
【每日一题Day302】LC849到最近的人的最大距离 | 贪心+分类讨论
【每日一题Day302】LC849到最近的人的最大距离 | 贪心+分类讨论
34 0
|
9月前
【动态规划刷题 16】最长等差数列 (有难度) && 等差数列划分 II - 子序列
【动态规划刷题 16】最长等差数列 (有难度) && 等差数列划分 II - 子序列
|
1月前
【错题集-编程题】最长上升子序列(二)(贪心 + 二分)
【错题集-编程题】最长上升子序列(二)(贪心 + 二分)
|
1月前
【每日一题Day170】LC1040移动石子直到连续 II | 双指针 贪心 数学
【每日一题Day170】LC1040移动石子直到连续 II | 双指针 贪心 数学
32 1
|
1月前
【每日一题Day261】LC16最接近的三数之和 | 双指针
【每日一题Day261】LC16最接近的三数之和 | 双指针
24 0
|
1月前
【每日一题Day192】LC1033移动石子直到连续 | 分类讨论 贪心
【每日一题Day192】LC1033移动石子直到连续 | 分类讨论 贪心
23 0
|
1月前
【每日一题Day306】LC228汇总区间 | 双指针
【每日一题Day306】LC228汇总区间 | 双指针
24 0
|
1月前
【每日一题Day122】LC1237找出给定方程的正整数解 | 双指针 二分查找
【每日一题Day122】LC1237找出给定方程的正整数解 | 双指针 二分查找
26 0
|
1月前
【每日一题Day223】LC1130叶值的最小代价生成树 | 贪心 区间dp
【每日一题Day223】LC1130叶值的最小代价生成树 | 贪心 区间dp
29 0