【LeetCode2834】美丽数组的最小和
问题描述
给定两个正整数:n 和 target
如果数组 nums 满足下述条件,则称其为 美丽数组 。
1)nums.length == n.
2)nums 由两两互不相同的正整数组成。
3)在范围 [0, n-1] 内,不存在 两个 不同 下标 i 和 j ,使得 nums[i] + nums[j] == target 。
返回符合条件的美丽数组所可能具备的 最小 和,并对结果进行取模 10^9 +7。
举例
示例 1:
输入:n = 2, target = 3
输出:4
解释:nums = [1,3] 是美丽数组。
- nums 的长度为 n = 2 。
- nums 由两两互不相同的正整数组成。
- 不存在两个不同下标 i 和 j ,使得 nums[i] + nums[j] == 3 。
可以证明 4 是符合条件的美丽数组所可能具备的最小和。
示例 2:
输入:n = 3, target = 3
输出:8
解释:
nums = [1,3,4] 是美丽数组。
- nums 的长度为 n = 3 。
- nums 由两两互不相同的正整数组成。
- 不存在两个不同下标 i 和 j ,使得 nums[i] + nums[j] == 3 。
可以证明 8 是符合条件的美丽数组所可能具备的最小和。
示例 3:
输入:n = 1, target = 1
输出:1
解释:nums = [1] 是美丽数组。
思路挖掘
1)试想一个简单的问题,从[1, n]中取任意互不相等的数取n个,答案就是[1,n]这n个数,这是贪心算法的起源。
所以对于
条件2:nums 由两两互不相同的正整数组成;
满足这一条件,我们只需要运用贪心思想即可,即从1开始选择。
2)再设想一个问题,对于条件3,任意两个数相加不可以等于target.
假设任意两个数为a和b, 且a+b=target,则在选数的时候,如果选了a,则不能再选b.
推广:
对于target,选择1则放弃taeget-1,由于要确保和最小,所以我们从小数开始选。
假设target为奇数。例如target==7
则待选的结果如下:1,2,3,4,5,6,可选的结果为1,2,3
假设target为偶数。例如target==8
则待选的结果如下:1,2,3,4,5,6,7可选的结果为1,2,3,4
综上可知,对于target而言,可选的结果为1~target/2 整除
若target = 10 而 n = 3呢,那自然直接选1,2,3就行,所以当n小于target/2的值时,直接选n就行。
这里我们定义:
m
=
m
i
n
(
n
,
⌊
t
a
r
g
e
t
2
⌋
)
m=min(n,\lfloor\frac{target}{2}\rfloor)
m=min(n,⌊2target⌋)
即此时我们已经选出m个数,并且这m个数是连续的,对于连续的数,和为
s
u
m
1
=
m
∗
(
m
+
1
)
2
sum_1 =\frac{m*(m+1)}{2}
sum1=2m∗(m+1)
最后我们还需要满足条件1,即n个数,由于n一定是大于等于m的,故而我们还需要选择(n - m )个数
1
——
m
——
t
a
r
g
e
t
——
n
1——m——target——n
1——m——target——n
我们知道,对于前m个数,我们是在1~target/2中进行选择的,由于要满足条件3,所以剩余的数我们只能从target开始选,一直选出(n-m)个连续的数即可。
则下一次选数的范围为:
[
t
a
r
g
e
t
,
t
a
r
g
e
t
+
n
−
m
−
1
]
[target, target+n-m-1]
[target,target+n−m−1]
则该(n-m)个数的和为:
s
u
m
2
=
(
2
∗
t
a
r
g
e
t
+
n
−
m
+
1
)
2
∗
(
n
−
m
)
sum_2 = \frac{(2*target+n-m+1)}{2}*(n-m)
sum2=2(2∗target+n−m+1)∗(n−m)
综上,满足条件的美丽数组的最小和为:
m
i
n
s
u
m
=
(
2
∗
t
a
r
g
e
t
+
n
−
m
+
1
)
∗
(
n
−
m
)
+
m
∗
(
m
+
1
)
2
minsum=\frac{(2*target+n-m+1)*(n-m)+m*(m+1)}{2}
minsum=2(2∗target+n−m+1)∗(n−m)+m∗(m+1)
其中
m
=
m
i
n
(
n
,
⌊
t
a
r
g
e
t
2
⌋
)
m=min(n,\lfloor\frac{target}{2}\rfloor)
m=min(n,⌊2target⌋)
代码展示
class Solution:
def minimumPossibleSum(self, n: int, target: int) -> int:
m = min(target // 2, n)
ans = ((1 + m) * m //2 +(2 * target + n - m -1)*(n - m) //2) % (10**9 + 7)
return ans
天天做题,天天好运