leeched-day5

动态规划

  1. 53最大子数组和
    题目描述:
    给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。
    53.最大子数组和
    思路:
    首先需要把题意理解清楚,要找到一个具有最大和的连续子数组。比较重要的是最大和,连续子数组。
    我们可以将每一个子问题dp[i]定义为以nums[i]结尾的具有最大和的连续子数组,然后对于每一个子问题,我们的状态转移方程可以定义为dp[i] = max{dp[i]+nums[i],dp[i]};如果nums[i]>0,那么dp[i]=dp[i]+nums[i],否则dp[i]=nums[i],也就是说,dp[i] = max{dp[i]+nums[i],dp[i]}
    关键代码:
       for (int i = 1; i < nums.length; i++) {
            dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
            maxValue = Math.max(maxValue,dp[i]);
        }

简化代码,我们可以用一个变量来代替dp[i],即代码可以变成

        int pre = 0;//当前最大连续子数组和
        int res = nums[0];//最大连续子数组和
        for (int num : nums) {
            pre = Math.max(pre + num, num);
            res = Math.max(res, pre);
        }
  1. 918.环形子数组的最大和
    题目描述:
    给定一个长度为 n 的环形整数数组 nums ,返回 nums 的非空 子数组 的最大可能和 。
    环形数组 意味着数组的末端将会与开头相连呈环状。形式上, nums[i] 的下一个元素是 nums[(i + 1) % n] , nums[i] 的前一个元素是 nums[(i - 1 + n) % n] 。
    子数组 最多只能包含固定缓冲区 nums 中的每个元素一次。形式上,对于子数组 nums[i], nums[i + 1], ..., nums[j] ,不存在 i <= k1, k2 <= j 其中 k1 % n == k2 % n 。
    918.环形子数组的最大和
    思路:
    这道题跟53最大子数组和类似,区别就是这道题的最大和数组可能是环形的,而上一题是线性的。所以相当于这道题是在上一题的基础上添加了一种可能性。
    看了国外的那个题解,感觉思路就顿时开阔了,真的厉害。
    我们要求最大连续子数组和,加一个环形数组的条件就有两种情况,分别是:
    1. 跟53一样,最大连续子数组出现在数组的中间部分。
    2.最大连续子数组出现在数组的首尾,从而构成一个环形
    image
    如果是第二种情况的话,因为数组的总和是一样的,那么我们可以知道,如果首尾连接所得到的值最大的话,那么中间部分所得到的值就是最小的。
    image
    所以对于第一种情况,我们可以使用53的方法,记录连续子数组的最大和,对于第二种情况,记录连续子数组的最小和,如果是最小和,那么就需要用数组的和减去最小和,即的连续子数组的最大和。
    关键代码:
      for(int i = 1;i<nums.length;i++){
            currentMax = Math.max(currentMax+nums[i],nums[i]);
            maxValue = Math.max(currentMax,maxValue);
            currentMin = Math.min(currentMin+nums[i],nums[i]);
            minValue = Math.min(currentMin,minValue);
            total += nums[i];
        }

到这里我们就求到了整个连续子数组的最大和和最小和,那么我们怎么知道此时的数组是第一种还是第二种情况呢?
我们可以知道,如果说是第二种情况,那么我们的最大和就是total-minValue,于是我们就可以将total-minValuemaxValue比较,取较大的那个值。
但是此时有一种特殊情况,如果说最大连续子数组的和是负数,那么此时数组的值一定全是负数,于是计算所得的最小值等于整个数组和,minValue=total,此时total-minValue=0,此时这种情况是有问题的。所以说如果最大和是负数,那么我们的连续子数组最大和就是maxValue,否则才是max(maxValue,total-minValue),即方法返回 return maxValue>0?Math.max(maxValue,total-minValue):maxValue;
这种思路最妙的一点就在于整个数组值是固定的,如果某个连续子数组和最大,那么剩余的环形子数组和就该最小;反之亦然。
但是有一种特殊情况是数组的值全是负数或者正数的情况,如果数组值全是正数,那么连续子数组最小和以及连续子数组最大和还有总和都相等;如果数组全是负数,那么连续子数组最小和以及数组总和相等。我们要规避这些情况发生所以最后还需要处理一下返回值。

posted @   达杰瑞如归  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 我与微信审核的“相爱相杀”看个人小程序副业
· DeepSeek “源神”启动!「GitHub 热点速览」
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示