leetcode
leetcode 2401 ~ 2450
找出美丽数组的最小和

找出美丽数组的最小和

难度:

标签:

题目描述

You are given positive integers n and target.

An array nums is beautiful if it meets the following conditions:

  • nums.length == n.
  • nums consists of pairwise distinct positive integers.
  • There doesn't exist two distinct indices, i and j, in the range [0, n - 1], such that nums[i] + nums[j] == target.

Return the minimum possible sum that a beautiful array could have modulo 109 + 7.

 

Example 1:

Input: n = 2, target = 3
Output: 4
Explanation: We can see that nums = [1,3] is beautiful.
- The array nums has length n = 2.
- The array nums consists of pairwise distinct positive integers.
- There doesn't exist two distinct indices, i and j, with nums[i] + nums[j] == 3.
It can be proven that 4 is the minimum possible sum that a beautiful array could have.

Example 2:

Input: n = 3, target = 3
Output: 8
Explanation: We can see that nums = [1,3,4] is beautiful.
- The array nums has length n = 3.
- The array nums consists of pairwise distinct positive integers.
- There doesn't exist two distinct indices, i and j, with nums[i] + nums[j] == 3.
It can be proven that 8 is the minimum possible sum that a beautiful array could have.

Example 3:

Input: n = 1, target = 1
Output: 1
Explanation: We can see, that nums = [1] is beautiful.

 

Constraints:

  • 1 <= n <= 109
  • 1 <= target <= 109

代码结果

运行时间: 16 ms, 内存: 16.1 MB


/*
思路:
1. 为了避免 nums[i] + nums[j] == target,我们需要选择 nums 中的元素,使得没有两个数之和等于 target。
2. 使用 Java Stream 来生成和处理数组。
3. 最小的 n 个正整数的和是 1 + 2 + ... + n = n * (n + 1) / 2。
4. 遍历数组,若出现 nums[i] + nums[j] == target,则替换 nums[j] 为 nums[j] + 1。
5. 取模 10^9 + 7 返回最终结果。
*/

import java.util.stream.IntStream;

public class BeautifulArrayStream {
    public int beautifulArray(int n, int target) {
        int mod = 1000000007;
        long sum = IntStream.rangeClosed(1, n).sum();
        int i = 1;
        while (i <= n && sum % target == 0) {
            sum = (sum - i + (i + 1)) % mod;
            i++;
        }
        return (int) (sum % mod);
    }
}

解释

方法:

此题解的核心思路是通过数学方法计算出美丽数组的最小和。首先,它通过计算m=min(k//2,n),确定数组中最小值部分的数目m。这是因为在数组中任意两个数之和不能等于给定的目标值k,因此选择数值尽可能小的m个数可以确保它们的和小于k。接着题解利用了算术级数求和的公式来计算前m个自然数的和以及剩余部分的和,通过这种方式可以快速得到整个数组的和。最后,为了处理可能的大数字,结果对1_000_000_007取模来满足题目要求。

时间复杂度:

O(1)

空间复杂度:

O(1)

代码细节讲解

🦆
如何确定取m=min(k//2, n)的逻辑能够确保数组中任意两个不同的数的和不等于target?
选择m=min(k//2, n)是为了保证在数值范围内尽可能地避免任意两个数的和等于target。当我们取数值从1开始到m时,最大可能的和是m*(m+1)/2,这一和小于k,因为m最大为k//2。这样做可以确保在选择的这些数中,不会有任何两个数的和达到或超过target,这是因为最大的两个数之和也仅为2*m,而2*m最大是k,但不包括k。因此,这种选择有效避免了和为target的情况。
🦆
在计算前m个数的和以及m到n-1的数的和时,为什么使用等差数列求和公式,这样的数列分布对解题有什么帮助?
在解题中使用等差数列求和公式是因为这可以快速计算连续数列的和。前m个自然数是一个简单的等差数列,其和可以直接使用公式m*(m+1)/2来计算,这样的计算非常高效。对于m到n-1的数,我们可以假设这些数是接续的最小的数,确保和最小,同样形成一个等差数列。使用等差数列的求和公式可以快速计算出这部分的和,提高了效率。整体来说,这种数列的选择和分布有助于快速且准确地计算出整个数组的和,从而寻找到满足条件的最小和。
🦆
题解中没有详细说明如何选择这些数值,具体是如何选择这些数使得它们两两之间的和不等于target的?
题解中通过计算m=min(k//2, n)来选择数值,确保选取的每个数从1到m,这些数是最小的m个正整数。由于m是k的一半,所以任意两个这样的数相加,其和最大为2*m,这小于k。这样就保证了这些数两两相加不会等于target。对于m之后到n-1的数,题解选择继续使用大于m的最小整数,即从m+1开始,以此类推,这些数加起来的和同样不会恰好等于target,因为它们的起始点已经大于m,和会超过k。

相关问题