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 。

提示:

  • n == nums.length
  • 1 <= n <= 3 * 104
  • -3 * 104 <= nums[i] <= 3 * 104​​​​​​​

 

 

解题思路:

  与常规求最大连续子数组和问题相比,该题多出来一种情况,那就是和最大的连续子数组在首尾处(如下图所示)。这种情况下,最大连续子数组和 = 数组总和 - 最小连续子数组和(也即图中空白处)

    

 

   

  因此,为了方便起见,我直接用两次遍历来分别计算出常规的最大连续子数组和max以及常规的最小连续子数组和min,同时也统计数组总和sum。最后比较(max)与(sum-min)取较大值。由于题目要求不允许空子数组,因此在初始化时都设为数组的第一个值。若是允许空子数组,可以初始化为0。

class Solution {
    public int maxSubarraySumCircular(int[] nums) {
        int sum = 0;
        int max = nums[0];
        int prev = 0;
        for(int i=0;i<nums.length;i++){
            sum += nums[i];  //顺便计算数组总和
            prev = Math.max(prev+nums[i],nums[i]);
            max = Math.max(max,prev);
        }
        prev = 0;
        int min = nums[0]; 
        for(int i=0;i<nums.length;i++){
            prev = Math.min(prev+nums[i],nums[i]);
            min = Math.min(min,prev);
        }
        if(sum != min){    
           max = Math.max(max,sum-min);
        }
        return max;  //当最小子数组为整个数组时,sum-min会导致结果为0,因此这种情况就无需比较max和sum-min,直接返回max即可
} }

 

 

 

 

 
posted @ 2022-04-05 21:15  ˙鲨鱼辣椒ゝ  阅读(177)  评论(0)    收藏  举报