# 题目描述
给定一个长度为 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
# 测试用例
示例 1:
- 输入:
nums = [1,-2,3,-2]
- 输出:3
- 解释:从子数组 [3] 得到最大和 3
示例 2:
- 输入:
nums = [5,-3,5]
- 输出:10
- 解释:从子数组
[5,5]
得到最大和5 + 5 = 10
示例 3:
- 输入:
nums = [3,-2,2,-3]
- 输出:3
- 解释:从子数组
[3]
和[3,-2,2]
都可以得到最大和 3
# 思路
参考代码注释
# 代码实现
var __readline = require("readline-sync");
__readline.setDefaultOptions({ prompt: "" });
var readline = __readline.prompt;
console.log("请输入nums数组:");
const nums = readline()
.split(",")
.map((item) => parseInt(item));
/**
* @param {number[]} nums
* @return {number}
*/
var maxSubarraySumCircular = function (nums) {
// 环形子数组最大
// 两种情况
// 1. 子数组没有用到环形,相当于计算最大非空子数组和
// 2. 子数组用到了环形,—— 相当于数组的总和 - 非空子数组和最大 —— 即求最小非空子数组和
// 最后返回两种情况的最大值即可
// 注意特殊情况,最小非空子数组就是整个数组 —— 那我们就不考虑情况二 —— 直接返回情况一
// 5 -9 4 4 -9 5
let max1 = Number.MIN_SAFE_INTEGER; // 情况1
let maxChild = 0;
let min2 = 0; // 情况2
let minChild = 0;
let sum = 0;
for (let i = 0; i < nums.length; i++) {
// 求最大非空子数组和 —— 以nums[i - 1]结尾的子数组选或不选
// Math.max(maxChild, 0)就是如果有前边的是负数了,那就不选前边的元素了
maxChild = Math.max(maxChild, 0) + nums[i];
max1 = Math.max(max1, maxChild);
minChild = Math.min(minChild, 0) + nums[i];
min2 = Math.min(min2, minChild);
sum += nums[i];
}
return sum === min2 ? max1 : Math.max(max1, sum - min2);
};
const res = maxSubarraySumCircular(nums);
console.log("结果为: ", res);
/*
请输入nums数组:
1,-2,3,-2
结果为: 3
请输入nums数组:
5,-3,5
结果为: 10
请输入nums数组:
3,-2,2,-3
结果为: 3
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60