数组、链表专题
- 前缀和数组
- LeetCode 303. 区域和检索 - 数组不可变
- 解题思路
- 代码实现
- LeetCode 304. 二维区域和检索 - 矩阵不可变
- 解题思路
- 代码实现
- 总结
不要纠结,干就完事了,熟练度很重要!!!多练习,多总结!!!
前缀和数组
LeetCode 303. 区域和检索 - 数组不可变
解题思路
核心思路是我们 new 一个新的数组preSum出来,preSum[i]记录nums[0…i-1]的累加和,看图 10 = 3 + 5 + 2:
看这个preSum数组,如果我想求索引区间[1, 4]内的所有元素之和,就可以通过preSum[5] - preSum[1]得出。
这样,sumRange函数仅仅需要做一次减法运算,避免了每次进行 for 循环调用,最坏时间复杂度为常数O(1)。
代码实现
class NumArray {
int[] preSum;
public NumArray(int[] nums) {
preSum = new int[nums.length +1];
for(int i = 1;i < preSum.length;i++){
preSum[i] = preSum[i-1]+nums[i-1];
}
}
public int sumRange(int left, int right) {
return preSum[right+1]-preSum[left];
}
}
LeetCode 304. 二维区域和检索 - 矩阵不可变
解题思路
如果我想计算红色的这个子矩阵的元素之和,可以用绿色矩阵减去蓝色矩阵减去橙色矩阵最后加上粉色矩阵,而绿蓝橙粉这四个矩阵有一个共同的特点,就是左上角就是(0, 0)原点。
那么我们可以维护一个二维preSum数组,专门记录以原点为顶点的矩阵的元素之和,就可以用几次加减运算算出任何一个子矩阵的元素和。
代码实现
class NumMatrix {
int[][] preSum;
public NumMatrix(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
preSum = new int[m+1][n+1];
for(int i = 1;i <= m;i++){
for(int j = 1;j <= n;j++){
preSum[i][j] = preSum[i-1][j]+preSum[i][j-1]+matrix[i-1][j-1]-preSum[i-1][j-1];
}
}
}
public int sumRegion(int row1, int col1, int row2, int col2) {
return preSum[row2+1][col2+1]-preSum[row2+1][col1]-preSum[row1][col2+1]+preSum[row1][col1];
}
}
总结
本题来源于Leetcode中 归属于数组、链表类型题目。
同许多在算法道路上不断前行的人一样,不断练习,修炼自己!
如有博客中存在的疑问或者建议,可以在下方留言一起交流,感谢各位!
觉得本博客有用的客官,可以给个点赞+收藏哦! 嘿嘿
喜欢本系列博客的可以关注下,以后除了会继续更新面试手撕代码文章外,还会出其他系列的文章!