题目链接:. - 力扣(LeetCode)
题目描述
给你两个正整数:n
和 target
。如果数组 nums
满足下述条件,则称其为 美丽数组 。
nums.length == n
.nums
由两两互不相同的正整数组成。- 在范围
[0, n-1]
内,不存在 两个 不同 下标i
和j
,使得nums[i] + nums[j] == target
。
返回符合条件的美丽数组所可能具备的 最小 和,并对结果进行取模 109 + 7
。
示例 1:
输入:n = 2, target = 3 输出:4 解释:nums = [1,3] 是美丽数组。 - nums 的长度为 n = 2 。 - nums 由两两互不相同的正整数组成。 - 不存在两个不同下标 i 和 j ,使得 nums[i] + nums[j] == 3 。 可以证明 4 是符合条件的美丽数组所可能具备的最小和。
解题思路
这道题要求 n 个正整数的最小和,满足这 n 个数中任意两个数的和并不等于 target。
首先如果不考虑限制条件(任意两个元素和不等于 target),根据贪心策略,n 个正整数的最小和肯定是 [1, n] 这个 n 个数。但是现在加了限制条件,[1, n] 中有些元素就不能选了,那么是哪些元素不能选呢?
因此我们首先可以选择 [1, target/2]这部分范围的元素,共 target / 2个元素。这部分元素和可以利用等差数列公式得到(记 k1 = target / 2):s1 = (1 + k1) * k1 / 2。
那么剩下的 n - target 个元素肯定从 target 开始往后取。
总的元素和就等于这两部分的元素和,即为最小和。
!!!要注意你前面选的 target / 2 有可能已经满足 n 个元素了。因此 k1 = min(n, target / 2)。当 k1 取到 n 时,k2 即为 0.
复杂度分析
时间复杂度:O(1)
空间复杂度:O(1)
代码
#include <vector>
#include <iostream>
using namespace std;
class Solution
{
public:
int minimumPossibleSum(int n, int target)
{
const int MOD = 1000000007;
long long k1 = min(n, target / 2); // [1, target - 1]内提供的元素个数
long long k2 = n - k1; // [target, ...)提供的元素个数
return ((1 + k1) * k1 + (2 * target + k2 - 1) * k2) / 2 % MOD;
}
};
int main()
{
Solution solution;
int n = 2;
int target = 3;
int res = solution.minimumPossibleSum(n, target);
cout << res << endl;
n = 3;
target = 3;
res = solution.minimumPossibleSum(n, target);
cout << res << endl;
n = 1;
target = 1;
res = solution.minimumPossibleSum(n, target);
cout << res << endl;
}