分糖果 II
Distribute Candies to People
解
方法一:暴力法
遍历一遍,这里有一点小优化,即假设最后一名正好分完,最后再把多的糖果减去,这样少了一行判断
class Solution {
public:
vector<int> distributeCandies(int candies, int num_people) {
int i = 0;
vector<int>ret(num_people, 0);
while (candies > 0) {
ret[i % num_people] += i + 1;
candies -= i + 1;
i++;
}
ret[(i - 1) % num_people] += candies;
return ret;
}
};
方法二:等差数列
除了最后一份以外,其他礼物的数量都是从 1 开始构成的等差数列。
假设有complete
份完整礼物,糖果总数量为C
剩余糖果为
r
e
m
a
i
n
i
n
g
=
C
−
∑
k
=
0
c
o
m
p
l
e
t
e
p
=
C
−
∑
k
=
0
c
o
m
p
l
e
t
e
p
(
p
−
1
)
2
remaining=C-\sum_{k=0}^{complete} {p}=C-\sum_{k=0}^{complete}{\frac{p(p-1)}{2}}
remaining=C−k=0∑completep=C−k=0∑complete2p(p−1)
且我们知道
0
≤
r
e
m
a
i
n
i
n
g
<
c
o
m
p
l
e
t
e
+
1
0 \leq remaining < complete+1
0≤remaining<complete+1
化简得
2
C
+
1
4
−
2
3
<
c
o
m
p
l
e
t
e
≤
2
C
+
1
4
−
1
2
\sqrt{2C+\frac{1}{4}}-\frac{2}{3} <complete \leq \sqrt{2C+\frac{1}{4}}-\frac{1}{2}
2C+41−32<complete≤2C+41−21
即
c
o
m
p
l
e
t
e
=
⌊
2
C
+
1
4
−
1
2
⌋
complete=\lfloor \sqrt{2C+\frac{1}{4}}-\frac{1}{2} \rfloor
complete=⌊2C+41−21⌋
将complete
份完整的礼物分发给 N 个人,共可以分发的回合数:rows = complete / N
。
在rows
个完整回合中,第 i 个人获得礼物
r
e
t
[
i
]
=
i
+
(
i
+
N
)
+
(
i
+
2
N
)
+
(
i
+
(
r
o
w
s
−
1
)
N
)
=
i
×
r
o
w
s
+
N
r
o
w
s
(
r
o
w
s
−
1
)
2
ret[i]=i+(i+N)+(i+2N)+(i+(rows−1)N)=i×rows+N \frac{rows(rows-1)}{2}
ret[i]=i+(i+N)+(i+2N)+(i+(rows−1)N)=i×rows+N2rows(rows−1)
在最后一个回合中,可以计算出收到完整礼物的人数 cols = p % N
他们得到的
r
e
t
[
i
]
+
=
i
+
N
×
r
o
w
s
ret[i]+=i+N×rows
ret[i]+=i+N×rows
最后一名
r
e
t
[
c
o
l
s
]
+
=
r
e
m
a
i
n
i
n
g
ret[cols]+=remaining
ret[cols]+=remaining
最后返回ret即可
class Solution {
public:
vector<int> distributeCandies(int candies, int num_people) {
vector<int>ret(num_people, 0);
int complete = (int)(sqrt(2 * candies + 0.25) - 0.5);
int remaining = (int)(candies - (complete + 1) * complete * 0.5);
int rows = complete / num_people;
int cols = complete % num_people;
for (int i = 0; i < num_people; i++) {
ret[i] = (i + 1) * rows + (int)(rows * (rows - 1) * 0.5) * num_people;
if (i < cols) {
ret[i] += i + 1 + rows * num_people;
}
}
ret[cols] += remaining;
return ret;
}
};