前缀和:中心下标与数组乘积

文章目录

一、左右信息的统一视角

对于下标 i,可以把数组拆成三部分:

text 复制代码
[0, i) + nums[i] + (i, n)

中心下标比较左右两侧的和;除自身以外数组的乘积则把左右两侧的乘积相乘。两题的共同点是都不需要在处理每个 i 时重新扫描左右区间。

二、寻找数组的中心下标

LeetCode 724. 寻找数组的中心下标

设 dp[i] 表示下标 i 左侧所有元素的和,那么 dp[nums.length] 就是整个数组的总和。

如果 i 是中心下标,则有:

text 复制代码
左侧和 = 右侧和
dp[i] = dp[nums.length] - dp[i] - nums[i]

移项后可以直接判断:

text 复制代码
dp[i] * 2 + nums[i] == dp[nums.length]

这样只需要一个前缀和数组,不必再建立后缀和数组。代码从左向右检查,因此找到的第一个结果自然是最靠左的中心下标。

java 复制代码
class Solution {
    public int pivotIndex(int[] nums) {
        long[] dp = new long[nums.length + 1];
        for (int i = 1; i < nums.length + 1; i++) {
            dp[i] = dp[i - 1] + nums[i - 1];
        }

        for (int i = 0; i < nums.length; i++) {
            if (dp[i] * 2 + nums[i] == dp[nums.length]) {
                return i;
            }
        }
        return -1;
    }
}

时间复杂度为 O(n),空间复杂度为 O(n)。按照本题约束,int 足以保存总和;这里使用 long 可以降低代码对数值范围的依赖。

三、除了自身以外数组的乘积

LeetCode 238. 除了自身以外数组的乘积

如果先求全部元素的乘积,再除以 nums[i],遇到 0 时就无法处理,而且题目本身也要求不使用除法。可以分别保存左侧前缀积和右侧后缀积:

  • dpleft[i]:下标 0 到 i - 1 的元素乘积;
  • dpright[i]:下标 i 到 len - 1 的元素乘积。

因此,下标 i 的答案为:

text 复制代码
ret[i] = dpleft[i] * dpright[i + 1]

数组两端没有元素的一侧按乘法单位元 1 处理,所以初始化 dpleft[0] = 1、dpright[len] = 1。

java 复制代码
class Solution {
    public int[] productExceptSelf(int[] nums) {
        int len = nums.length;
        int[] dpleft = new int[len + 1];
        int[] dpright = new int[len + 1];

        dpleft[0] = 1;
        dpright[len] = 1;
        for (int i = 0; i < len; i++) {
            dpleft[i + 1] = dpleft[i] * nums[i];
        }
        for (int i = len - 1; i >= 0; i--) {
            dpright[i] = dpright[i + 1] * nums[i];
        }

        int[] ret = new int[len];
        for (int i = 0; i < len; i++) {
            ret[i] = dpleft[i] * dpright[i + 1];
        }
        return ret;
    }
}

题目保证相关前缀积、后缀积与答案都在 32 位整数范围内,因此可以使用 int[]。时间复杂度为 O(n),额外空间复杂度为 O(n)。

相关推荐
信奥卷王5 小时前
[GESP202609 六级] 分树规划
算法
夏幻灵5 小时前
LeetCode 21:合并两个有序链表——双指针与哑节点详解
算法·leetcode·链表
徐小黑ACG7 小时前
Golang 基础05 结构体struct
开发语言·算法·golang
码完就睡7 小时前
数据结构——红黑树
数据结构
码爸7 小时前
数据结构详细介绍
数据结构
Navigator_Z7 小时前
LeetCode //C - 1286. Iterator for Combination
c语言·算法·leetcode
北极有牛8 小时前
cpp学习笔记--常量指针
java·开发语言·算法
GPU实战笔记8 小时前
云端 GPU 训练的账户余额提醒:它能说明什么,不能说明什么?
深度学习·算法·成本管理·gpu云计算·云端训练
浮链序8 小时前
怎么证明"你这个模型是偷我的"——把蒸馏变成取证工具
算法·安全·llm