文章目录
- 前缀和模板
- 724. 寻找数组的中心下标
- 238. 除自身以外数组的乘积
- 560. 和为 K 的子数组
- 974. 和可被 K 整除的子数组
- 525. 连续数组
- 1314. 矩阵区域和
前缀和模板
一维前缀和:
import java.util.*;public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt(),q = scan.nextInt();int[] arr = new int[n + 1];long[] dp = new long[n + 1];for(int i = 1;i <= n;i++) {arr[i] = scan.nextInt();dp[i] = dp[i - 1] + arr[i];}while(q > 0) {int l = scan.nextInt(),r = scan.nextInt();System.out.println(dp[r] - dp[l - 1]);q--;}}
}
二维前缀和:
import java.util.*;public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt(),m = scan.nextInt(),q = scan.nextInt();int[][] arr = new int[n + 1][m + 1];long[][] dp = new long[n + 1][m + 1];for(int i = 1;i <= n;i++) {for(int j = 1;j <= m;j++) {arr[i][j] = scan.nextInt();dp[i][j] = arr[i][j] + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];}}while(q > 0) {int x1 = scan.nextInt(),y1 = scan.nextInt();int x2 = scan.nextInt(),y2 = scan.nextInt();System.out.println(dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1]);q--;}}
}
724. 寻找数组的中心下标
给你一个整数数组 nums ,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。
如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。
class Solution {public int pivotIndex(int[] nums) {int n = nums.length;int[] f = new int[n];int[] g = new int[n];for(int i = 1;i < n;i ++) {f[i] = f[i - 1] + nums[i - 1];}for(int j = n - 2;j >= 0;j--) {g[j] = g[j + 1] + nums[j + 1];}for(int i = 0;i < n;i++) {if(f[i] == g[i]) {return i;}}return -1;}
}
238. 除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题。
class Solution {public int[] productExceptSelf(int[] nums) {int n = nums.length;int[] f = new int[n];int[] g = new int[n];f[0] = 1;g[n - 1] = 1;for(int i = 1;i < n;i++) {f[i] = f[i - 1] * nums[i - 1];}for(int i = n - 2;i >= 0;i--) {g[i] = g[i + 1] * nums[i + 1];}int[] ret = new int[n];for(int i = 0;i < n;i++) {ret[i] = f[i] * g[i];}return ret;}
}
560. 和为 K 的子数组
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。
class Solution {public int subarraySum(int[] nums, int k) {Map<Integer,Integer> hash = new HashMap<>();hash.put(0,1);int sum = 0, ret = 0;for(int x : nums) {sum += x;ret += hash.getOrDefault(sum - k,0);hash.put(sum,hash.getOrDefault(sum,0) + 1);}return ret;}
}
974. 和可被 K 整除的子数组
给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。
子数组 是数组的 连续 部分。
class Solution {public int subarraysDivByK(int[] nums, int k) {Map<Integer,Integer> hash = new HashMap<>();hash.put(0,1);int sum = 0,ret = 0;for(int x : nums) {sum += x;int r = (sum % k + k) % k;ret += hash.getOrDefault(r,0);hash.put(r,hash.getOrDefault(r,0) + 1);}return ret;}
}
525. 连续数组
给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。
class Solution {public int findMaxLength(int[] nums) {Map<Integer,Integer> hash = new HashMap<>();hash.put(0,-1); //默认存在一个前缀和为0的情况int sum = 0,ret = 0;for(int i = 0; i < nums.length;i++) {sum += (nums[i] == 0 ? -1 : 1);if(hash.containsKey(sum)) {ret = Math.max(ret,i - hash.get(sum));} else {hash.put(sum,i);}}return ret;}
}
1314. 矩阵区域和
给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和:
i - k <= r <= i + k, j - k <= c <= j + k 且(r, c) 在矩阵内。
class Solution {public int[][] matrixBlockSum(int[][] mat, int k) {int m = mat.length,n = mat[0].length;int[][] dp = new int[m + 1][n + 1];for(int i = 1;i <= m;i++) {for(int j = 1;j <= n;j++) {dp[i][j] = mat[i - 1][j - 1] + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];}}int[][] ret = new int[m][n];for(int i = 0;i < m;i++) {for(int j = 0;j < n;j++) {int x1 = Math.max(0,i - k) + 1;int y1 = Math.max(0,j - k) + 1;int x2 = Math.min(m - 1,i + k) + 1;int y2 = Math.min(n - 1,j + k) + 1;ret[i][j] = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1-1][y1-1];}}return ret;}
}