一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【LeetCode 1588. 所有奇数长度子数组的和 】- JavaScript(暴力+规律)
题意描述
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。
子数组 定义为原数组中的一个连续子序列。
请你返回 arr 中 所有奇数长度子数组的和 。
示例 1:
输入:arr = [1,4,2,5,3]
输出:58
解释:所有奇数长度子数组和它们的和为:
[1] = 1 [4] = 4 [2] = 2 [5] = 5 [3] = 3 [1,4,2] = 7 [4,2,5] = 11 [2,5,3] = 10 [1,4,2,5,3] = 15 我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58
思路分析:
很容易可以发现这是一道规律题。每个数字所在的区间有两种情况:
- 数左半边区间有奇数个,右半边奇数个;
- 数左半区间偶数个,右半区间偶数个;
等价于即左边奇位数*右边奇位数+左边偶位数*右边偶位数
暴力解法
核心思想:如果实在没有想出来规律,不妨冲它一波,暴力出奇迹。具体就是把每个符合要求的数全部加起来就行了。原地累计和
- 如果奇数为1,把整个数组累加起来。把output初始值设为所有数字累加之后的值。
- 第二个奇数3开始遍历以3为长度的子数组,把子数组的值都累加到output。
- 接下来遍历以5为长度的子数组,同理推导,如果长度已经超过了原数组的大小,就停下来
注意点:
- 时间复杂度为
O(n^3)。
var sumOddLengthSubarrays = function (arr) {
var res = 0;
function handle(arr, nums) {
for (var i = 0; i < arr.length; i++) {
var a = arr.slice(i, nums + i);
if (a.length < nums) {
break;
}
res += a.reduce((a1, b1) => {
return a1 + b1
})
}
}
for (var nums = 1; nums <= arr.length; nums += 2) {
handle(arr, nums);
}
return res;
};
完全背包
思想:如果慢慢发现题目的规律,并且总结出来,那么这道题就简单了,将O^3的复杂度直接到O,质的飞跃。就像最开始的我们说的规律,其中一个很重要的逻辑一定要注意奇 + 1 + 奇 = 奇,偶 + 1 + 偶 = 奇。这可以说是关键.那么久回到开头说的即左边奇位数*右边奇位数+左边偶位数*右边偶位数
注意:注意精度问题,避免舍去造成的误差。尤其是js没有整形
var sumOddLengthSubarrays = function (arr) {
var output = 0;
var len = arr.length;
for (let i = 0; i < len; i++) {
let left = i + 1,
right = len - i,
left_odd = Math.floor((left + 1) / 2),
left_even = Math.floor(left / 2),
right_odd = Math.floor((right + 1) / 2),
right_even = Math.floor(right / 2);
output += (left_even * right_even + left_odd * right_odd) * arr[i];
}
return output;
};
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤