给定一个数组和一个正整数N,求一个和小于N的最长连续子数组
头条算法题
相关代码
// 请把代码文本粘贴到下方(请勿用图片代替代码)
// 请把代码文本粘贴到下方(请勿用图片代替代码)
可以用动态规划的思想去看,
设 S(i) 为以第 i 个元素结尾的和小于 N 的最长连续数组
设 len(i) 为 S(i) 的长度
设 sum(i) 为 S(i) 的和
边界:
否则
不停归并 S(i) 左边相邻的 S(i-len(i)) ,直到 sum(i) 不再小于 N
最后根据最长的 len 返回数组即可
function lsa (arr, n) {
if (arr.length <= 0) { return [] }
// 1
const len = [arr[0] < n ? 1 : 0]
const sum = [arr[0]]
for (let i = 1; i < arr.length; i++) {
if (arr[i] >= n) { // 2
len[i] = 0
sum[i] = arr[i]
} else { // 3
// 3.1
len[i] = 1
sum[i] = arr[i]
// 3.2
for (let j = i - len[i]; j >= 0 && sum[i] < n; j = i - len[i]) {
sum[i] += sum[j]
len[i] += len[j] || 1 // 3.2.1
}
// 3.3
for (let j = i + 1 - len[i]; j < i && sum[i] >= n; j++) {
len[i] -= 1
sum[i] -= arr[j]
}
}
}
const max = len.reduce((max, l, i) => l > len[max] ? i : max, 0)
return arr.slice(max + 1 - len[max], max + 1)
}
function getMaxSubArr(arr, target) {
if (arr.length === 1) {
return arr[0] < target ? arr : [];
}
const dp = [[arr[0]]];
for (let i = 1; i < arr.length; i++) {
const c = arr[i];
const lastDp = dp[i - 1];
const sum = lastDp.reduce((acc, cur) => acc + cur, 0);
// 理想情况,直接追加
if (c + sum < target && lastDp[lastDp.length - 1] === arr[i - 1]) {
dp[i] = [...dp[i - 1], c];
} else {
// 尝试往回找个更好的
if (c < target) {
const newArr = [];
let sumDiff = target;
let j = i;
let newItem = arr[j];
while (j >= 0 && sumDiff >= newItem) {
sumDiff -= newItem;
newArr.unshift(newItem);
j--;
newItem = arr[j];
}
dp[i] = dp[i - 1].length > newArr.length ? dp[i - 1] : newArr;
} else {
// 都比target大了,无话可说
dp[i] = dp[i - 1];
}
}
}
return dp[arr.length - 1];
}
10 回答11.7k 阅读
2 回答3.2k 阅读✓ 已解决
3 回答2.7k 阅读✓ 已解决
4 回答2.2k 阅读✓ 已解决
3 回答1.2k 阅读✓ 已解决
3 回答1.9k 阅读✓ 已解决
3 回答805 阅读✓ 已解决