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——所有奇数长度子数组的和(前缀和)的主要内容,如果未能解决你的问题,请参考以下文章
[E前缀和] lc1588. 所有奇数长度子数组的和(前缀和+数学)
[E前缀和] lc1588. 所有奇数长度子数组的和(前缀和+数学)
LeetCode 1480. 一维数组的动态和 / 1588. 所有奇数长度子数组的和 / 528. 按权重随机选择(随机化)