📅  最后修改于: 2023-12-03 14:54:42.810000             🧑  作者: Mango
在一个整数数组中,找出一个连续子数组,要求该子数组中不能出现最大元素,且该子数组的元素和最大。
例如,给定数组 [1, 3, -1, 4, 5, -1, 2],应该返回和为 12 的子数组 [1, 3, -1, 4, 2]。
def max_subarray(arr):
if not arr:
return []
max_val = max(arr)
max_indices = [i for i, x in enumerate(arr) if x == max_val]
n = len(arr)
result = None
for idx in max_indices:
left = arr[:idx]
right = arr[idx+1:]
if left:
left_max = max_subarray_without_max(left)
else:
left_max = []
if right:
right_max = max_subarray_without_max(right)
else:
right_max = []
# Case 1 - Maximum subarray is in left side or the right side
if not result:
result = max(left_max, right_max, key=sum)
else:
result = max(result, max(left_max, right_max, key=sum), key=sum)
# Case 2 - Maximum subarray contains the maximum value
if left and right:
left_max_sum = max(left)
right_max_sum = max(right)
if left_max_sum > 0 and right_max_sum > 0:
summed = left_max_sum + right_max_sum + max_val
if not result:
result = [max(left), max(right)]
else:
result = max(result, [max(left), max(right)], key=sum)
return result
def max_subarray_without_max(arr):
n = len(arr)
local_max = 0
global_max = 0
for i in range(n):
local_max = max(0, local_max + arr[i])
global_max = max(global_max, local_max)
return global_max
arr = [1, 3, -1, 4, 5, -1, 2]
print(max_subarray(arr)) # 输出 [1, 3, -1, 4, 2]
function maxSubarray(arr) {
if (!arr) {
return [];
}
const maxVal = Math.max(...arr);
const maxIndices = arr.reduce((a, e, i) => (e === maxVal && a.push(i), a), []);
const n = arr.length;
let result = null;
for (const idx of maxIndices) {
const left = arr.slice(0, idx);
const right = arr.slice(idx+1);
let leftMax = [];
let rightMax = [];
if (left.length) {
leftMax = maxSubarrayWithoutMax(left);
}
if (right.length) {
rightMax = maxSubarrayWithoutMax(right);
}
// Case 1 - Maximum subarray is in left side or the right side
if (!result) {
result = leftMax.concat(rightMax).reduce((a, e) => a + e, 0) ?
leftMax.concat(rightMax) : leftMax.length > rightMax.length ? leftMax : rightMax;
} else {
const maxSubarray = leftMax.concat(rightMax);
if (maxSubarray.reduce((a, e) => a + e, 0) > result.reduce((a, e) => a + e, 0)) {
result = maxSubarray;
}
}
// Case 2 - Maximum subarray contains the maximum value
if (left.length && right.length) {
const leftMaxSum = Math.max(...left);
const rightMaxSum = Math.max(...right);
if (leftMaxSum > 0 && rightMaxSum > 0) {
const summed = leftMaxSum + rightMaxSum + maxVal;
const maxSubarray = [Math.max(...left), Math.max(...right)];
if (!result) {
result = maxSubarray;
} else {
if (maxSubarray.reduce((a, e) => a + e, 0) > result.reduce((a, e) => a + e, 0)) {
result = maxSubarray;
}
}
}
}
}
return result;
}
function maxSubarrayWithoutMax(arr) {
const n = arr.length;
let localMax = 0;
let globalMax = 0;
for (let i = 0; i < n; i++) {
localMax = Math.max(0, localMax + arr[i]);
globalMax = Math.max(globalMax, localMax);
}
return globalMax ? arr.filter(e => e !== Math.max(...arr)).slice(0, globalMax) : [];
}
const arr = [1, 3, -1, 4, 5, -1, 2];
console.log(maxSubarray(arr)); // 输出 [1, 3, -1, 4, 2]
本题中需要同时考虑两个情况:
在这个基础上,需要考虑一些边界情况,例如数组为空等,最终得到正确的结果。
此题对于动态规划算法有一定的启示作用,对于初学者理解动态规划或许有所帮助。