每日一题——从一个范围内选择最多整数 I

129 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情


这是昨天双周赛的第二题,题意很好理解,但是在比赛的时候会因为一些细节踩坑,无论什么时候,对于各种情况的把控一点要考虑清楚,不要过度相信测试用例。

6304.从一个范围内选择最多整数 I

给你一个整数数组 banned 和两个整数 n 和 maxSum 。你需要按照以下规则选择一些整数:

  • 被选择整数的范围是 [1, n] 。
  • 每个整数 至多 选择 一次 。
  • 被选择整数不能在数组 banned 中。
  • 被选择整数的和不超过 maxSum 。

请你返回按照上述规则 最多 可以选择的整数数目。

 

示例 1:

输入: banned = [1,6,5], n = 5, maxSum = 6
输出: 2
解释: 你可以选择整数 2 和 4 。
2 和 4 在范围 [1, 5] 内,且它们都不在 banned 中,它们的和是 6 ,没有超过 maxSum 。

示例 2:

输入: banned = [1,2,3,4,5,6,7], n = 8, maxSum = 1
输出: 0
解释: 按照上述规则无法选择任何整数。

示例 3:

输入: banned = [11], n = 7, maxSum = 50
输出: 7
解释: 你可以选择整数 1, 2, 3, 4, 5, 6 和 7 。
它们都在范围 [1, 7] 中,且都没出现在 banned 中,它们的和是 28 ,没有超过 maxSum 。

 

提示:

  • 1 <= banned.length <= 104
  • 1 <= banned[i], n <= 104
  • 1 <= maxSum <= 109

思路

拿到这个题目的第一反应是先找出可以选择的整数,然后将这些整数排序,因为题目要求的是选择最多的数目,故整数越小,可以选择到的整数个数就越多,所以使用贪心的策略,由小到大地选择出整数。

换个视角,我们从一到 n 进行遍历,如果出现不能被选择的数字,就将其跳过,若没有出现,就将其加入到被选择的数字中,具体做法为将计数总数加一,并将最大限制和减去该被选择的整数。以下题解中的两个 for 循环可以合成一个,由于当时比赛时间紧张,没有考虑过多。

还有一个坑,对于 banned 数组来说,里面的元素会出现重复,虽然不符合常理,但题目上也没有说明数组元素不重复,故对于重复元素,我们需要跳过。

题解

class Solution {
    public int maxCount(int[] banned, int n, int maxSum) {
        List<Integer> list = new ArrayList<>();
        Arrays.sort(banned);
        for(int i = 1, j = 0; i <= n; i++) {
            if(j < banned.length && banned[j] == i) {
                j++;
                while(j < banned.length && banned[j] == banned[j - 1]) {
                    j++;
                }
            }else {
                list.add(i);
            }
        }
        int cnt = 0;
        for(int i = 0; i < list.size() && maxSum > 0; i++) {
            if(list.get(i) <= maxSum) {
                maxSum -= list.get(i);
                cnt++;
            }
        }
        return cnt;
    }
}

如果你有其他的思路或者更好的解法,亦或者你发现了文章出现了错误或有不足,欢迎在评论区和我交流,我看到了一定会回复。

写文章不易,如果你觉得文章对你有帮助,麻烦点一下点赞、收藏,你的支持是我写文章的最大动力!