题解 | 分糖果问题
分糖果问题
https://www.nowcoder.com/practice/76039109dd0b47e994c08d8319faa352
这题核心就一句话:
每个孩子至少 1 个糖果,且要同时满足“左约束”和“右约束”
如果只从一个方向考虑,一定会漏掉另一边的约束。
什么要两次遍历?
假设数组:
1 2 3 2 1
如果你只从左往右:
1 2 3 1 1 ❌
后面递减部分不满足规则。
如果只从右往左:
1 1 3 2 1 ❌
前面递增部分又错了。
所以:
- 左→右:解决“比左边高”
- 右→左:解决“比右边高”
两边都要满足。
第一步:初始化
每个人至少一个糖果
candies = [1,1,1,1,...]
第二步:从左往右
如果:
arr[i] > arr[i-1]
说明当前分数更高
那当前糖果必须比左边多:
candies[i] = candies[i-1] + 1
这一步保证:
✅ 所有“上坡”满足规则
第三步:从右往左
如果:
arr[i] > arr[i+1]
说明当前分数更高
那当前糖果必须比右边多:
candies[i] = max(candies[i], candies[i+1] + 1)
⚠️ 注意一定要取 max!
因为左往右已经分过一次,不能把之前满足左侧规则的结果破坏掉。
package main
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* pick candy
* @param arr int整型一维数组 the array
* @return int整型
*/
func candy( arr []int ) int {
// write code here
res := []int{}
n := len(arr)
for i := 0; i<n; i++{
res[i] = 1
}
for i:=1; i<n; i++{
if arr[i]>arr[i-1]{
res[i] = res[i-1]+1
}
}
for j:=n-2; j>=0;j--{
if arr[j]>arr[j+1]{
res[j] = max(res[j],res[j+1]+1)
}
}
candy:=0
for i:=0;i<n;i++{
candy += res[i]
}
return candy
}
func max(a,b int) int {
if a>b{
return a
}
return b
} 哪里有问题
1)res := []int{} 之后你直接用 res[i] = 1
res := []int{} 是长度为 0 的切片,没有任何元素,所以 res[i] 会 直接 panic:index out of range。
✅ 正确做法:先分配长度 n
res := make([]int, n)for i := 0; i < n; i++ { res[i] = 1}
或者更简洁(make 默认就是 0,再赋值 1 也行):
res := make([]int, n)for i := range res { res[i] = 1}
2)边界:如果 n==0(虽然题目一般 n≥1,但写健壮一点)
加一句:
if n == 0 { return 0 }
查看13道真题和解析