Leetcode——所有奇数长度子数组的和(前缀和)

Posted Yawn,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——所有奇数长度子数组的和(前缀和)相关的知识,希望对你有一定的参考价值。

1. 所有奇数长度子数组的和

(1)暴力三重循环

class Solution {
    public int sumOddLengthSubarrays(int[] arr) {
        int sum = 0;
        int len = arr.length;

        // i 用于控制子数组长度
        for (int i = 1; i <= len; i+= 2) {

            //j用于控制子数组起点
            for (int j = 0; j + i <= len; j++) {

                //实际控制长度
                for (int x = 0; x < i; x++) {   
                    sum += arr[x + j];
                }
            }
        }
        return sum;
    }
}


(2)双指针 + 前缀和

  • 先计算出当前数组的前缀和,并保存
  • 使用left、right双指针遍历,如果(right - left + 1) % 2 == 1,说明left到right是奇数数组,那么计算该范围的元素和就可以直接利用前缀和nums[right] - nums[left] + arr[i]得到
class Solution {

    public int sumOddLengthSubarrays(int[] arr) {
        int len = arr.length;

        int[] nums = new int[len];
        int res = 0;
        nums[0] = arr[0];

        // 计算前缀和,包括arr[i]的前缀和
        for (int i = 1; i < len; i++) {
            nums[i] = nums[i - 1] + arr[i];
        }
        
        int left = 0,right = 0;
        int tmp = 0;
        while (left < len) {
            right = left;
            while (right < len) {
                tmp = right - left + 1;
                if (tmp % 2 == 1) {
                    //利用前缀和计算元素和
                    res += nums[right] - nums[left] + arr[left];
                }
                right++;
            }
            left++;
        }

        return res;
    }
}

(3)DP(效率低)

class Solution {
    public int sumOddLengthSubarrays(int[] arr) {
        int n = arr.length;

        // f[i][j] 表示数组下标 i 开始连续 j 个的数和
        int[][] dp = new int[n][n+1];
        
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += dp[i][1] = arr[i];
            for (int j = 3; i + j <= n; j += 2) {
                sum += dp[i][j] = dp[i][j-2] + arr[i+j-2]  + arr[i+j-1];
            }
        }

        return sum;
    }
}


以上是关于Leetcode——所有奇数长度子数组的和(前缀和)的主要内容,如果未能解决你的问题,请参考以下文章

1588. 所有奇数长度子数组的和前缀和

[E前缀和] lc1588. 所有奇数长度子数组的和(前缀和+数学)

[E前缀和] lc1588. 所有奇数长度子数组的和(前缀和+数学)

leetcode所有奇数长度子数组的和

LeetCode 1480. 一维数组的动态和 / 1588. 所有奇数长度子数组的和 / 528. 按权重随机选择(随机化)

LeetCode523. 连续的子数组和