Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
给定一个长度为 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 。
示例 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
提示:
n == nums.length1 <= n <= 3 * 104-3 * 104 <= nums[i] <= 3 * 104
题解
这道题还是比较考察思路的,在上一道题LC-53. 最大子数组和
-
我们可以找到 无环状态下最大值
-
相应的我们也可以找到 无环状态下最小子数组和
如何考虑有环状态呢?
对有两种情况进行比较大小。
-
情况1
获取 无环状态下最大值
-
情况2
我们知道一个公式: (最大值 = 数组总和 - 最小值)
若想求最大值,就是 总和 减去 最小的 就是 最大值。
-
但是会出现一种情况,就是数组里全是 负数
这里我们会对这种情况处理的,其实就等于情况1的 无环状态下最大值
此时就会解决 有环状态 的情况。
-
我们可以看到 贪心 的效率,还是很高的。
贪心
const maxSubarraySumCircular = (nums) => {
const numsLength = nums.length
let sum1 = 0
let max1 = nums[0]
let sum2 = 0
let min2 = nums[0]
let sum3 = 0
let max3 = nums[0]
for (let i = 0; i < numsLength; i++) {
sum3 += nums[i]
if (sum1 >= 0) {
sum1 += nums[i]
} else {
sum1 = nums[i]
}
if (sum2 <= 0) {
sum2 += nums[i]
} else {
sum2 = nums[i]
}
max1 = max1 > sum1 ? max1 : sum1
min2 = min2 < sum2 ? min2 : sum2
}
// 如果最小值大于0,那么将 sum3 赋值 max3
if (min2 > 0) max3 = sum3
// 如果最小值小于0
if (min2 < 0) {
// 判断最小值和sum3是否相等
if (sum3 === min2) {
// 如果相等,则说明nums全是负数或者0,直接找数组中最大值 给 max3 即可
max3 = max1
} else {
// 如果不相等,根据公式 ( 最大 = 总和 - 最小 )
max3 = sum3 - min2
}
}
// 最后比较一下,无环和有环状态下谁最大
return Math.max(max1, max3)
}
总结
该题目 33 :注意这道题的解题思路 和 贪心 方法的使用。