方法一 暴力循环
遍历数组的每一个元素,找寻该元素所有连续长度为奇数的可能,累加奇数长度区间内的所有元素。
比如对于[1,4,2,5,3] ,对于第一个元素1,有[1]、[1,4,2]、[1,4,2,5,3]这三种可能,对于第二个元素4,有[4]、[4,2,5]这两种可能,以此类推,反复累加最后得到sum
var sumOddLengthSubarrays = function(arr) {
let sum=0
for(let i=0;i<arr.length;i++){
for(let len=1;i+len<=arr.length;len+=2){
let end=i+len-1
for(let j=i;j<=end;j++){
sum+=arr[j]
}
}
}
return sum
};
消耗时间和内存情况:
方法二 前缀和
对于方法一中循环求每种可能的奇数长度数组的和可以进行优化,能少嵌套一层for循环
构造前缀和数组prefixSums,数组每一项prefixSums[i]保存的是数组arr从下标0到下标i-1的元素和
var sumOddLengthSubarrays = function(arr) {
let sum=0
let prefixSums = new Array(arr.length+1).fill(0)
for(let i=0;i<arr.length;i++){
prefixSums[i+1]=prefixSums[i]+arr[i]
}
for(let i=0;i<arr.length;i++){
for(let len=1;i+len<=arr.length;len+=2){
let end=i+len-1
sum+=prefixSums[end+1]-prefixSums[i]
}
}
return sum
};
消耗时间和内存情况:
方法三 数学
大致思路是:
数组中每个元素都会在不同长度的奇数子数组中出现一次或多次,只要计算出每个元素在多少个长度为奇数的子数组中出现,就能得到所有奇数长度子数组的和
作者:力扣官方题解
链接:leetcode1588.所有奇数长度子数组的和
var sumOddLengthSubarrays = function(arr) {
let sum = 0;
const n = arr.length;
for (let i = 0; i < n; i++) {
const leftCount = i, rightCount = n - i - 1;
const leftOdd = Math.floor((leftCount + 1) / 2);
const rightOdd = Math.floor((rightCount + 1) / 2);
const leftEven = Math.floor(leftCount / 2) + 1;
const rightEven = Math.floor(rightCount / 2) + 1;
sum += arr[i] * (leftOdd * rightOdd + leftEven * rightEven);
}
return sum;
};
消耗时间和内存情况: