题解 | 小红的岁晚可可塔

小红的岁晚可可塔

https://www.nowcoder.com/practice/6b06f501f8154f57801590ca495f37ac

#include <stdio.h>
#define Max(a, b) ((a) > (b) ? (a) : (b))

/**
 * 求最大子数组和(滑动窗口法/Kadane算法变种)
 * @param nums 整数数组
 * @param n 数组长度
 * @return 最大子数组和
 */
int maxAnSum(int* nums, int n){
    int left = 0;        // 左指针(窗口左边界)
    int right;           // 右指针(窗口右边界)
    int maxSum = nums[0]; // 全局最大子数组和(初始化为第一个元素)
    int curSum = 0;       // 当前窗口的和

    for(right = 0; right < n; right++){
        // 1. 将当前元素加入窗口
        curSum += nums[right];

        // 2. 更新全局最大值
        maxSum = Max(maxSum, curSum);

        // 3. 如果当前窗口和为负数,收缩窗口直到和为非负
        //    因为负数窗口对后续求最大和没有帮助
        while(curSum < 0){
            curSum -= nums[left++];  // 移除左边元素,左指针右移
        }
    }

    return maxSum;
}

int main() {
    int n, i, nums[1000001];
    scanf("%d\n", &n);
    for(i = 0; i < n; i++){
        scanf("%d ", &nums[i]);
    }
    int res = maxAnSum(nums, n);
    printf("%d", res);
    return 0;
}

int maxAnSum(int* nums, int n){
    int left = 0, right, maxSum = 0;  // 错误1

    for(right = 0; right < n; right++){
        maxSum += nums[right];         // 错误2

        while(maxSum < maxSum - nums[right])  // 错误3
            maxSum -= nums[left++];    // 错误4
    }

    return maxSum;
}

错误点详细分析:

1. 变量混淆

maxSum既当窗口和又当最大和

一个变量承担两个职责,逻辑混乱

curSum记录当前窗口和,

maxSum只记录历史最大值

2. 初始化错误

maxSum = 0

如果数组全为负数,会返回0(错误)

maxSum = nums[0]保证返回真实的最大值

3. 循环条件错误

while(maxSum < maxSum - nums[right])

条件永远不成立,且逻辑意义不明

while(curSum < 0)当窗口和为负时才收缩

4. 窗口收缩逻辑

用奇怪的比较触发收缩

没有真正解决负数窗口的问题

当窗口和为负时,持续移除左边元素直到和非负

5. 更新时机错误

先更新maxSum再判断

顺序颠倒,逻辑混乱

先加入元素,再更新最大值,最后处理负数窗口

全部评论

相关推荐

03-10 11:23
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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