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

109 阅读2分钟

1. 题目与解析

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

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

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

输入: 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+4能组成7,一个硬币7也能组成7,那么前者的灵活性肯定是大于后者的。

好了,下面我们回到题目进行分析,我们需要计算的是一堆硬币能计算的从0开始的,能连续组合成的最大的数字,所以,如果某一工况下我们得到的答案为n,那么n-1也一定能组合出来。有了这一前提,我们就可以进行数学归纳了。

小硬币的灵活性更大,小硬币组合不出来的数字,换成更大面值的硬币也一定组合不出来,因此,首先进行一个从小到大的排序。

Arrays.sort(coins);

排序之后,我们就需要进行推理过程了,我们现假设,当我们取到第i个硬币之前,0-n的数字都能组合出来,那么加上i的面值,即ni-n+ni的值也一定能组合出来,唯一的问题是,我们需要判断ni的值与n的大小关系,如果n>=ni,那么两段范围就能连接上了,我们的答案就能更新到n+ni,如果不可以,那么就返回原来的答案n,另外,因为0也是一个数字,所以答案返回值初始化为1。

        int ans = 1;
        for (int coin: coins) {
            if (ans < coin) {
                break;
            }
            ans += coin;
        }
        return ans;

2. 题解

class Solution {
    public int getMaximumConsecutive(int[] coins) {
        int ans = 1;
        Arrays.sort(coins);
        for (int coin: coins) {
            if (ans < coin) {
                break;
            }
            ans += coin;
        }
        return ans;

    }
}