题解 | 分糖果问题

分糖果问题

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 }
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务