暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

918. Maximum Sum Circular Subarray环形数组的最大值

程序媛的梦想 2020-01-22
292

环形数组就是遍历到末尾之后又能回到开头继续遍历。既然是子数组,则意味着必须是相连的数字,而由于环形数组的存在,说明可以首尾相连,而且题目说明每个数字只能用一次。

思路:
1. 在固定长度的数组中求最大连续子数组的和,用Kadane算法。
2. 这道题是环形数组,这个的处理就有点巧妙了,并不是用%数组长度这种方法。
(1) 全是负数的特殊处理,这时判断的条件是所有数组元素之和sum = 最小连续子数组之和minInTotal
(2) 全是正数的特殊处理,这时判断的条件是所有数组元素之和sum = 最小连续子数组之和maxInTotal
(3) 其它情况,等于所有数组元素之和sum-最小连续子数组之和minInTotal
 1    public int maxSubarraySumCircular(int[] A) {
2        int maxTillHere = A[0];// 到目前为止的最大和
3        int maxInTotal = A[0];// 全局最大的连续子数组之和
4        int minTillHere = A[0];// 到目前为止的最小和
5        int minInTotal = A[0];// 全局最小的连续子数组之和
6        int sum = A[0];// 所有元素之和
7
8        for (int i = 1; i < A.length; i++) {
9            sum += A[i];
10            // 求最大连续子数组之和
11            if (maxTillHere + A[i] > A[i]) {// Kadane算法
12                maxTillHere += A[i];
13            } else {
14                maxTillHere = A[i];// 开始下一个连续子数组
15            }
16            maxInTotal = Math.max(maxInTotal, maxTillHere); // 更新全局最大
17
18            // 求最小连续子数组之和
19            if (minTillHere + A[i] < A[i]) {
20                minTillHere += A[i];
21            } else {
22                minTillHere = A[i];
23            }
24            minInTotal = Math.min(minInTotal, minTillHere);// 更新全局最小
25        }
26
27        if (sum == minInTotal) return maxInTotal;// 都是负数
28        return Math.max(sum - minInTotal, maxInTotal);// 都是正数,或有正有负的情况
29    }


附:Kadane算法:
就是遍历数组,记录累加和,每次看看累加和加上当前元素,看它们的和是否大于当前元素,如果大于则把之前的和加过来,如果小于则这个数就没必要加之前的和了,然后更新一下截止到这里的最大和maxTillHere,还得用一个变量maxInTotal来更新全局的最大值。
求最小的连续子数组的和也是一样的方法,只不过每次看是不是小于。
文章转载自程序媛的梦想,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论