每日一题——你能构造出连续值的最大数目

86 阅读2分钟

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


1798. 你能构造出连续值的最大数目

给你一个长度为 n 的整数数组 coins ,它代表你拥有的 n 个硬币。第 i 个硬币的值为 coins[i] 。如果你从这些硬币中选出一部分硬币,它们的和为 x ,那么称,你可以 构造 出 x 。

请返回从 0 开始(包括 0 ),你最多能 构造 出多少个连续整数。

你可能有多个相同值的硬币。

 

示例 1:

输入: coins = [1,3]
输出: 2
解释: 你可以得到以下这些值:
- 0:什么都不取 []
- 1:取 [1]
从 0 开始,你可以构造出 2 个连续整数。

示例 2:

输入: coins = [1,1,1,4]
输出: 8
解释: 你可以得到以下这些值:
- 0:什么都不取 []
- 1:取 [1]
- 2:取 [1,1]
- 3:取 [1,1,1]
- 4:取 [4]
- 5:取 [4,1]
- 6:取 [4,1,1]
- 7:取 [4,1,1,1]
从 0 开始,你可以构造出 8 个连续整数。

示例 3:

输入: nums = [1,4,10,3,1]
输出: 20

 

提示:

  • coins.length == n
  • 1 <= n <= 4 * 104
  • 1 <= coins[i] <= 4 * 104

思路

初次看到这个题的时候想到了动态规划,但思来想去并不好实现,因为涉及到使用过的硬币和未使用过的硬币,对于某种金币和来说,有可能有多种硬币的组合方式,无法一一验证。

然后想到了使用暴力解法试一试,先对硬币排序,对于每一个整数,由大到小地遍历数组,看是否能组合出该金额,这种方法的时间复杂度是n的二次方,最终还是超时。

看了一下官方解答,感觉有些数学解法的意思,首先我们用 [l,r] 表示一段连续的从 l 到 r 的连续整数区间,不妨设我们现在能构造出 [0,x] 区间的整数,现在我们新增一个整数 y,那么我们可以构造出的区间为 [0,x] 和 [y,x+y],那么如果 y≤x+1 ,则加入整数 y 后我们能构造出 [0,x+y] 区间的整数,否则我们还是只能构造出 [0,x] 区间的数字。

题解

class Solution {
    public int getMaximumConsecutive(int[] coins) {
        Arrays.sort(coins);
        int n = coins.length;
        int cnt = 0;
        for(int i = 0; i < n && coins[i] <= cnt + 1; i++) {
            cnt += coins[i];
        }
        return cnt + 1;
    }
}