1. 程式人生 > 其它 >Q1588所有奇數長度子陣列的和

Q1588所有奇數長度子陣列的和

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;
    }