基础算法之前缀和--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;
    }
}

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

我们下半部分见😁

相关推荐
7澄17 小时前
深入解析 LeetCode 1572:矩阵对角线元素的和 —— 从问题本质到高效实现
java·算法·leetcode·矩阵·intellij-idea
PieroPc7 小时前
用python Streamlit 做个RapidOCR 文本识别系统
开发语言·python·ocr
ALex_zry7 小时前
c20 字符串处理优化可选方案
算法
诗9趁年华7 小时前
缓存三大问题深度解析:穿透、击穿与雪崩
java·spring·缓存
阳光明媚sunny7 小时前
分糖果算法题
java·算法
whltaoin7 小时前
【JAVA全栈项目】弧图图-智能图床SpringBoot+MySQL API接口结合Redis+Caffeine多级缓存实践解析
java·redis·spring·缓存·caffeine·多级缓存
卡提西亚7 小时前
一本通网站1125题:矩阵乘法
c++·算法·矩阵·编程题·一本通
程序员东岸7 小时前
数据结构精讲:从栈的定义到链式实现,再到LeetCode实战
c语言·数据结构·leetcode
暖木生晖7 小时前
Javascript函数之匿名函数以及立即执行函数的使用方法?
开发语言·javascript·ecmascript
一 乐7 小时前
医疗管理|医院医疗管理系统|基于springboot+vue医疗管理系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·医疗管理系统