基础算法之前缀和--Java实现(上)--LeetCode题解:【模板】前缀和-【模板】二维前缀和-寻找数组的中心下标-除自身以外数组的乘积

这里是Themberfue

【模板】前缀和

题目解析

本题就是求给定两个索引的之间的数组和,比如:给定1和3下标索引,那么就求出,下标1到下标3所有元素的和即可。

算法讲解

· 利用前缀和可以快速求出数组中某一连续区间的和。

· 所以我们需要先预处理出来一个前缀和数组 dp[],dp[i] 表示 [1, i]这个区间数组的和。

· 根据推导,我们可以得出状态转移方程,也就是当前位置的前缀和等于上一个位置的前缀和加上当前位置数组的元素。即 dp[i] = dp[i - 1] + arr[i]。

· 为了防止 dp 数组下标越界访问,我们一般以 1 为起点计数。所以记得给 dp 数组的下标0位置初始为0。

· 但现在我们要求给定区间的和,有了 dp 数组就好求了,比如要求求出 [2, 5]的下标和,那么其实就是 dp[5] - dp[1]。

· 总结公式:[left, right] => dp[right] - dp[left - 1]

编写代码

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), q = sc.nextInt();

        // 创建前缀和数组
        long[] dp = new long[n + 1];
        for (int i = 1; i <= n; i++) {
            dp[i] = dp[i - 1] + sc.nextInt();
        }

        // 使用前缀和数组
        for (int i = 0; i < q; i++) {
            int left = sc.nextInt(), right = sc.nextInt();
            System.out.println(dp[right] - dp[left - 1]);
        }
    }
}

【模板】二维前缀和

题目解析

此题与上题类似,不过就是从一维数组变成了二维数组。 给定四个索引,表示数组的横排索引以及纵排索引,然后就是这个范围所代表的矩形区域的和。

算法讲解

· 本题的 dp[i][j] 表示 [1][1]到dp[i][j] 所构成的矩形区域的和。

· 根据数形结合来推导出状态转移方程。

· dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + arr[i][j] - dp[i - 1][j - 1]

· 同样的,为了防止数组下标越界访问,也是从1下标开始计数。

· 利用数形结合,同样推导出该公式。

· ret = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1]

编写代码

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt(), q = sc.nextInt();
        // 创建一个二维前缀和数组
        long[][] dp = new long[n + 1][m + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                dp[i][j] = dp[i - 1][j] + dp[i][j-1] + sc.nextInt() - dp[i-1][j-1];
            }
        }

        // 使用二位前缀数组
        for (int i = 0; i < q; i++) {
            int x1 = sc.nextInt(), y1 = sc.nextInt(), x2 = sc.nextInt(), y2 = sc.nextInt();
            System.out.println(dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1]);
        }
    }
}

寻找数组的中心下标

题目解析

返回一个下标,这个下标(不包括它自己)左边所有元素的和等于右边所有元素的和。

算法讲解

· 题目出现了某一个区间内的和,那应该想到使用前缀和。

· 左边所有元素的和便使用前缀和,但这个前缀和不应该包括它自身。

· 但右边所有元素的和应该使用后缀和,且这个后缀和也不应该包括它自身。

· 根据图示,前缀和数组应该从前往后遍历,公式为:f[i] = f[i - 1] + arr[i - 1],为了防止越界访问,前缀和数组的第0个位置记得初始化

· 根据图示,后缀和数组一个从后往前遍历,公式为:g[i] = g[i + 1] + arr[i + 1],为了防止越界访问,前缀和数组的第n - 1个位置记得初始化。

· 最后如果某一位置的前缀和和后缀和相同,那么该下标就满足题意。

编写代码

java 复制代码
class Solution {
    public int pivotIndex(int[] nums) {
        int n = nums.length;
        // 创建前缀和数组以及后缀和数组
        int[] f = new int[n];
        for (int i = 1; i < n; i++) 
            f[i] = f[i - 1] + nums[i - 1];

        int[] g = new int[n];
        for (int i = n - 2; i >= 0; i--)
            g[i] = g[i + 1] + nums[i + 1];

        // 使用前缀和数组以及后缀和数组
        for (int i = 0; i < n; i++) {
            if (f[i] == g[i]) 
                return i;
        }
        return -1;
    }
}

除自身以外数组的乘积

题目解析

本题表示对于当前下标,除了它自身以外的元素,返回其余元素的乘积。

算法讲解

· 这题与上题类似,只不过变成了前缀积和后缀积。

· 填完前缀积和后缀积后,之间返回它们对于下标的积即可。

编写代码

java 复制代码
class Solution {
    public int[] productExceptSelf(int[] nums) {
        int len = nums.length;
        // 创建前缀积数组以及后缀积数组
        int[] f = new int[len];
        f[0] = 1;
        for (int i = 1; i < len; i++) {
            f[i] = f[i - 1] * nums[i - 1];
        }

        int[] g = new int[len];
        g[len - 1] = 1;
        for (int i = len - 2; i >= 0; i--) {
            g[i] = g[i + 1] * nums[i + 1];
        }

        int[] ret = new int[len];
        // 使用前缀积数组以及后缀积数组
        for (int i = 0; i < len; i++) {
            ret[i] = f[i] * g[i];
        }
        return ret;
    }
}

好了,以上就是今天内容的全部讲解,如果有不懂的地方,随时私聊😘

我们下半部分见😁

相关推荐
jerryinwuhan3 小时前
最短路径问题总结
开发语言·人工智能·python
C嘎嘎嵌入式开发3 小时前
(1)100天python从入门到拿捏
开发语言·python
过往入尘土4 小时前
服务端与客户端的简单链接
人工智能·python·算法·pycharm·大模型
zycoder.4 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
软件开发技术深度爱好者4 小时前
用python制作相册浏览小工具
开发语言·python
又是忙碌的一天4 小时前
前端学习 JavaScript(2)
前端·javascript·学习
Dream it possible!4 小时前
LeetCode 面试经典 150_哈希表_存在重复元素 II(46_219_C++_简单)
leetcode·面试·散列表
2501_915106324 小时前
JavaScript编程工具有哪些?老前端的实用工具清单与经验分享
开发语言·前端·javascript·ios·小程序·uni-app·iphone
蒙奇D索大4 小时前
【数据结构】考研数据结构核心考点:二叉排序树(BST)全方位详解与代码实现
数据结构·笔记·学习·考研·算法·改行学it
玲娜贝儿--努力学习买大鸡腿版4 小时前
推荐算法学习笔记(十九)阿里SIM 模型
笔记·学习·推荐算法