42. 连续子数组的最大和

本文介绍了如何使用动态规划求解数组中最大连续子数组和的问题,时间复杂度为O(n)。示例给出了Java代码实现,通过维护一个以当前元素结尾的子数组最大和数组dp,并不断更新全局最大值res,最终得到最大子数组和。

剑指 Offer 42. 连续子数组的最大和

53.最大子数组和

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

要求时间复杂度为 O ( n ) O(n) O(n)

示例1:

输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

提示:

  • 1 <= arr.length <= 10^5
  • -100 <= arr[i] <= 100

注意:本题与主站 53 题相同:https://leetcode-cn.com/problems/maximum-subarray/

解题思路:动态规划

经典的dp问题,dp[i]表示以第i个元素结尾的连续子数组的最大和,则有

  • 之前以第i-1个元素结尾的连续子数组的最大和dp[i - 1]小于0时,那以第i个元素结尾的最大连续子数组的最大和dp[i]就是该元素本身nums[i]
  • 否则以第i个元素结尾的最大连续子数组的最大和dp[i]就是以第i-1个元素结尾的连续子数组的最大和dp[i-1]加上第i个元素的值nums[i]

即状态转移为:dp[i] = Math.max(dp[i - 1] ,0) + nums[i];

题目要求最大值,那我们用一个变量res保存最大值即可。

Java代码

class Solution {
    public int maxSubArray(int[] nums) {
        if(nums == null || nums.length == 0) return 0;
        int[] dp = new int[nums.length];
        
        dp[0] = nums[0];
        int res = dp[0];
        for(int i = 1;i < nums.length;i++){
            dp[i] = Math.max(dp[i - 1] ,0) + nums[i];
            res = Math.max(dp[i],res);
        }
        return res;
    }
}

在这里插入图片描述

解题思路二:贪心算法

贪心思路:当前数字前面的最大累加和如果是负数,只会拖累以当前数字为起点的最大累加和,那么就让当前数字做为新的连续子数组的起点,而如果之前的累加和是正数,则可以继续往后加,因为往后加可以得到更大的和

Go代码

func maxSubArray(nums []int) int {
    // 贪心思路:当前数字前面的最大累加和如果是负数,只会拖累以当前数字为起点的最大累加和,那么就让
    // 当前数字做为新的连续子数组的起点,而如果之前的累加和是正数,则可以继续往后加,因为往后加可以得到更大的和
    if len(nums) == 0{
        return 0
    }
    sum := 0
    res := math.MinInt32
    for i := 0;i < len(nums);i++ {
        if sum >= 0 {
            sum += nums[i]
        } else {
            sum = nums[i]
        }
        res = max(res,sum)
    }

    return res
}

func max(a,b int) int {
    if a > b {
        return a
    }
    return b
}

在这里插入图片描述

扩展题 Leetcode 485 最大连续 1 的个数

485. 最大连续 1 的个数

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 1:

输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.

示例 2:

输入:nums = [1,0,1,1,0,1]
输出:2

提示:

  • 1 <= nums.length <= 10^5
  • nums[i] 不是 0 就是 1.

解题思路

与上题思路几乎一模一样,不在赘述,直接上代码吧!

同样是动态规划和贪心都可以做,这里给出的是动态规划的代码

Go代码

func findMaxConsecutiveOnes(nums []int) int {
    // 假设dp[i]为以第i个数字结尾时连续1的个数
    // 状态转移方程:如果当前数字是0,则连续1个数将变为0(因为到此处时1将不再连续)
    // 当前数字是1,则dp[i] = dp[i-1]+1
    if len(nums) == 0 {
        return 0
    }
    dp := make([]int,len(nums))
    var res int
    if nums[0] == 1 {
        dp[0]  = 1
        res = 1
    } else {
        dp[0] = 0
        res = 0
    }

    for i := 1;i < len(nums);i++ {
        if nums[i] == 0 {
            dp[i] = 0
        } else {
            dp[i] = dp[i - 1] + 1
        }
        res = max(res,dp[i])
    }

    return res
}

func max(a,b int) int {
    if a > b {
        return a
    }
    return b
}

在这里插入图片描述

# 力扣hot100刷题记录表 ### 一,哈希部分 - [ ] 1. 两数之和 (简单) - [ ] 2. 字母异位词分组(中等) - [ ] 3. 最长连续序列(中等) ### 二,双指针部分 - [ ] 4. 移动零(简单) - [ ] 5. 盛水最多的容器 (中等) - [ ] 6. 三数之和 (中等) - [ ] 7. 接雨水(困难) ### 三,滑动窗口 - [ ] 8. 无重复字符的最长子串(中等) - [ ] 9. 找到字符中所有的字母异位词(中等) ### 四,子串 - [ ] 10. 和为k的子数组(中等) - [ ] 11. 滑动窗口最大值(困难) - [ ] 12. 最小覆盖子窜(困难) ### 五,普通数组 - [ ] 13. 最大子数组和(中等) - [ ] 14. 合并区间(中等) - [ ] 15. 轮转数组(中等) - [ ] 16. 除自身以外数组的乘积(中等) - [ ] 17. 缺失的第一个正数(困难) ### 六,矩阵 - [ ] 18. 矩阵置零(中等) - [ ] 19. 螺旋矩阵 (中等) - [ ] 20. 旋转图像 (中等) - [ ] 21. 搜索二维矩阵Ⅱ (中等) ### 七,链表 - [ ] 22. 相交链表 (简单) - [ ] 23. 反转链表 (简单) - [ ] 24. 回文链表 (简单) - [ ] 25. 环形链表 (简单) - [ ] 26. 环形链表Ⅱ (中等) - [ ] 27. 合并两个有序链表 (简单) - [ ] 28. 两数相加 (中等) - [ ] 29. 删除链表的倒数第 N 个结点 (中等) - [ ] 30. 两两交换链表中的节点 (中等) - [ ] 31. K个一组翻转链表 (困难) - [ ] 32. 随机链表的复制 (中等) - [ ] 33. 排序链表 (中等) - [ ] 34. 合并 K 个升序链表 (困难) - [ ] 35. LRU 缓存 (中等) ### 八,二叉树 - [ ] 36. 二叉树的中序遍历 (简单) - [ ] 37. 二叉树的最大深度 (简单) - [ ] 38. 翻转二叉树 (简单) - [ ] 39. 对称二叉树 (简单) - [ ] 40. 二叉树的直径 (简单) - [ ] 41. 二叉树的层序遍历 (中等) - [ ] 42. 将有序数组转换为二叉搜索树 (简单) - [ ] 43. 验证二叉搜索树 (中等) - [ ] 44. 二叉搜索树中第 K 小的元素 (中等) - [ ] 45. 二叉树的右视图 (中等) - [ ] 46. 二叉树展开为链表 (中等) - [ ] 47. 从前序与中序遍历序列构造二叉树 (中等) - [ ] 48. 路径总和 III (中等) - [ ] 49. 二叉树的最近公共祖先 (中等) - [ ] 50. 二叉树中的最大路径和 (困难) ### 九,图论 - [ ] 51. 岛屿数量 (中等) - [ ] 52. 腐烂的橘子 (中等) - [ ] 53. 课程表 (中等) - [ ] 54. 实现 Trie(前缀树) (中等) ### 十,回溯 - [ ] 55.全排列(中等) - [ ] 56.子集(中等) - [ ] 57.电话号码的字母组合(中等) - [ ] 58.组合总和(中等) - [ ] 59.括号生成(中等) - [ ] 60.单词搜索(中等) - [ ] 61.分割回文串(中等) - [ ] 62.N 皇后 (困难) ### 十一,二分查找 - [ ] 63. 搜索插入位置 (简单) - [ ] 64. 搜索二维矩阵 (中等) - [ ] 65. 在排序数组中查找元素的第一个和最后一个位置 (中等) - [ ] 66. 搜索旋转排序数组 (中等) - [ ] 67. 寻找旋转排序数组中的最小值 (中等) - [ ] 68. 寻找两个正序数组的中位数 (困难) ### 十二,栈 - [ ] 69. 有效的括号 (简单) - [ ] 70. 最小栈 (中等) - [ ] 71. 字符串解码 (中等) - [ ] 72. 每日温度 (中等) - [ ] 73. 柱状图中最大的矩形 (困难) ### 十三,堆 - [ ] 74. 数组中的第K个最大元素 (中等) - [ ] 75. 前K 个高频元素 (中等) - [ ] 76. 数据流的中位数 (闲难) ### 十四,贪心算法 - [ ] 77. 买卖股票的最佳时机 (简单) - [ ] 78. 跳跃游戏 (中等) - [ ] 79. 跳跃游戏 III (中等) - [ ] 80. 划分字母区间 (中等) ### 十五,动态规划 - [ ] 81. 爬楼梯(简单) - [ ] 82. 杨辉三角 (简单) - [ ] 83. 打家劫舍 (中等) - [ ] 84. 完全平方数 (中等) - [ ] 85. 零钱兑换 (中等) - [ ] 86. 单词拆分 (中等) - [ ] 87. 最长递增子序列 (中等) - [ ] 88. 乘积最大子数组 (中等) ### 十六,多维动态规划 - [ ] 91. 不同路径 (中等) - [ ] 92. 最小路径和 (中等) - [ ] 93. 最长回文子串 (中等) - [ ] 94. 最长公共子序列 (中等) - [ ] 95. 编辑距离 (中等) ### 十七,技巧 - [ ] 96. 只出现一次的数字 (简单) - [ ] 97. 多数元素 (简单) - [ ] 98. 颜色分类 (中等) - [ ] 99.一个排列 (中等) - [ ] 100. 寻找重复数 (中等) 如何使用
最新发布
07-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值