Q1588所有奇數長度子陣列的和
阿新 • • 發佈:2021-09-01
Q1588所有奇數長度子陣列的和
題目描述
給你一個正整數陣列 arr ,請你計算所有可能的奇數長度子陣列的和。
子陣列 定義為原陣列中的一個連續子序列。
請你返回 arr 中 所有奇數長度子陣列的和 。
示例一:
輸入: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
解法思路
解法一 暴力演算法
三重迴圈,時間複雜度O(n3)
public int sumOddLengthSubarrays(int[] arr) { int sum = 0; int n = arr.length; for (int i = 1; i <= n; i += 2) { for (int j = 0; j <= n - i; j++) { for (int k = j; k <= k + i - 1; k++) { sum += arr[k]; } } } return sum; }
解法二 字首和
利用字首和,能將時間複雜度降低為O(n2)
public int sumOddLengthSubArrays(int[] arr) { int sum = 0; int n = arr.length; int preSumNum = 0; int[] preSum = new int[n+1]; preSum[0] = 0; for (int i = 1; i <=n; i++) { preSumNum += arr[i-1]; preSum[i] = preSumNum; } for (int i = 1; i <= n; i += 2) { for (int j = 0; j <= n - i; j++) { sum+=preSum[j+i]-preSum[j]; } } return sum; }
解法三 數學
關鍵是統計arr[i]在奇數子陣列中出現的次數。
arr[i]在奇數子陣列中出現的條件是,在該陣列中,arr[i]左右兩側數字個數的奇偶性相同。
我們知道arr[i]左側有i個數,右側有n-i-1個數,於是可以求得組合次數
位置i左邊奇數個數的方案數為 (i+1)/2,右邊奇數個數方案為(n-i)/2;
位置i左邊偶數個數的方案數為 i/2,右邊偶數個數方案為(n-i-1)/2;
- 考慮左右兩邊不選也屬於合法的偶數個數方案數,因此在上述分析基礎上對偶數方案數自增 11。
組合起來,arr[i]在奇數陣列中出現的次數為k =(i+1)/2*(n-i)/2+ (i/2+1) * ((n-i-1)/2+1);
由此,可以得出時間複雜度為O(n1)
public int sumOddLengthSubArrays(int[] arr) {
int sum = 0;
int n = arr.length;
for (int i = 0; i < n; i++) {
int lo = (i + 1) / 2, ro = (n - i) / 2,
le = i / 2 + 1, re = (n - i - 1) / 2 + 1;
sum += (lo * ro + le * re) * arr[i];
}
return sum;
}