当前位置: 首页 > news >正文

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

        编写代码

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]

         编写代码

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个位置记得初始化。

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

        编写代码 

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;}
}

除自身以外数组的乘积

        题目解析

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

        算法讲解 

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

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

        编写代码 

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;}
}

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

我们下半部分见😁

 


http://www.mrgr.cn/news/44417.html

相关文章:

  • 【机器学习】网络安全——异常检测与入侵防御系统
  • 自动驾驶传感器系列—自动驾驶中的“眼睛”:摄像头技术详解
  • 多模态技术全面概述:核心原理、关键技术与未来趋势
  • 陈文自媒体:小红书商单,情况如何?
  • 分析CppCrash(进程崩溃)(一)
  • java并发之并发实践
  • 关于srsUE、srsENB和srsEPC的功能列表
  • 【数学二】一元函数微分学-导数的计算-对数求导法、 参数方程确定得函数求导法
  • OpenCV:图像直方图计算
  • 身份证二要素-身份证二要素接口-身份证尔雅欧批量核验
  • PHP函数 strstr() 和 stristr() 有什么区别
  • 数据库-分库分表
  • c++继承(下)
  • 习题-位运算
  • 快递物流跟踪:掌握最后更新时间,高效筛选单号管理
  • 若依权限设计与自定义新增用户
  • 数据分析之Spark框架介绍
  • VMware Tanzu Kubernetes Grid Integrated Edition 1.20 发布下载,新增功能概览
  • JS中浅拷贝和深拷贝的区别
  • 解锁数字化营销成功密码