[1. 寻找数组的中心下标](#1. 寻找数组的中心下标)[2. 除了自身以外数组的乘积](#2. 除了自身以外数组的乘积)[3. 和为K的子数组](#3. 和为K的子数组)[4. 和可被K整除的子数组](#4. 和可被K整除的子数组)
[5. 连续数组](#5. 连续数组)[6. 搜索二维矩阵](#6. 搜索二维矩阵)[7. 矩阵区域和⭐](#7. 矩阵区域和⭐)
1. 寻找数组的中心下标
LCR 012. 寻找数组的中心下标
https://leetcode.cn/problems/tvdfij/
给你一个整数数组
nums,请计算数组的 中心下标 。数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组最左端,那么左侧数之和视为
0,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回
-1。
cppclass Solution { public: int pivotIndex(vector<int>& nums) { int total = 0; for (int num : nums) { total += num; } int sum = 0; for (int i = 0; i < nums.size(); ++i) { sum += nums[i]; if (total - sum == sum - nums[i]) { return i; } } return -1; } };思路:前缀和 + 后缀和
2. 除了自身以外数组的乘积
238. 除了自身以外数组的乘积
https://leetcode.cn/problems/product-of-array-except-self/
给你一个整数数组
nums,返回 数组answer,其中answer[i]等于nums中除了nums[i]之外其余各元素的乘积 。题目数据 保证 数组
nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。请 不要使用除法,且在
O(n)时间复杂度内完成此题。写法一:前缀和后缀
cppclass Solution { public: vector<int> productExceptSelf(vector<int>& nums) { vector<int> prenums,lastnums,result; int i=1,x=1; for(auto& e:nums) { i*=e; prenums.emplace_back(i); } for(int j=nums.size()-1;j>=0;--j) { x*=nums[j]; lastnums.emplace_back(x); } int add; for(int q=0;q<nums.size();q++) { if(q==0) add=lastnums[nums.size()-2]; else if(q==nums.size()-1) add=prenums[nums.size()-2]; else add=prenums[q-1]*lastnums[nums.size()-q-2]; result.emplace_back(add); } return result; } };写法二:前缀和后缀
cppclass Solution { public: vector<int> productExceptSelf(vector<int>& nums) { int len = nums.size(); if (len == 0) return {}; vector<int> ans(len, 1); ans[0] = 1; int tmp = 1; for (int i = 1; i < len; i++) { ans[i] = ans[i - 1] * nums[i - 1]; } for (int i = len - 2; i >= 0; i--) { tmp *= nums[i + 1]; ans[i] *= tmp; } return ans; } };
3. 和为K的子数组
560. 和为 K 的子数组
https://leetcode.cn/problems/subarray-sum-equals-k/
给你一个整数数组
nums和一个整数k,请你统计并返回 该数组中和为k的子数组的个数。子数组是数组中元素的连续非空序列。
cppclass Solution { public: int subarraySum(vector<int>& nums, int k) { unordered_map<int,int> kv={{0,1}}; int add=0,i=0; for(auto& e:nums) { add+=e; auto it=kv.find(add-k); if(it!=kv.end()) i+=it->second; kv[add]++; } return i; } };
4. 和可被K整除的子数组
974. 和可被 K 整除的子数组
https://leetcode.cn/problems/subarray-sums-divisible-by-k/
给定一个整数数组
nums和一个整数k,返回其中元素之和可被k整除的非空 子数组 的数目。子数组 是数组中 连续 的部分。
cppclass Solution { public: int subarraysDivByK(vector<int>& nums, int k) { unordered_map<int,int> hash={{0,1}}; int sum=0,r,count=0; for(auto& e:nums) { sum+=e; r=(sum%k+k)%k; if(hash.count(r)) count+=hash[r]; hash[r]++; } return count; } };
5. 连续数组
525. 连续数组
https://leetcode.cn/problems/contiguous-array/
给定一个二进制数组
nums, 找到含有相同数量的0和1的最长连续子数组,并返回该子数组的长度。写法一:哈希+前缀和
cppclass Solution { public: int findMaxLength(vector<int>& nums) { unordered_map<int, int> m = {{0,-1}}; int cur = 0, ans = 0; for(int i = 0; i < nums.size(); ++i) { nums[i] == 0? --cur : ++cur; if(m.count(cur)) ans = max(ans, i - m[cur]); else m[cur] = i; } return ans; } };写法二:哈希+dp
cppclass Solution { public: int findMaxLength(vector<int>& nums) { int n = nums.size(); int res = 0; unordered_map<int,int> first_ID; //第一次出现的位置 first_ID[0] = -1; //dp初始化 int cnt0 = 0, cnt1 = 0; for (int i = 0; i < n; i ++) { cnt0 += (nums[i] == 0); cnt1 += (nums[i] == 1); int d = cnt0 - cnt1; //平衡因子 if (first_ID.count(d)) res = max(res, i - first_ID[d]); else first_ID[d] = i; } return res; } };
6. 搜索二维矩阵
74. 搜索二维矩阵
https://leetcode.cn/problems/search-a-2d-matrix/
给你一个满足下述两条属性的
m x n整数矩阵:
- 每行中的整数从左到右按非严格递增顺序排列。
- 每行的第一个整数大于前一行的最后一个整数。
给你一个整数
target,如果target在矩阵中,返回true;否则,返回false。写法一:二分查找
cppclass Solution { public: bool searchMatrix(vector<vector<int>>& matrix, int target) { int left=0,right=matrix[0].size()-1,floor=0; while(left<right&&floor<matrix.size()) { while(floor<matrix.size()&&target>matrix[floor][right]) floor++; if(floor==matrix.size()) return false; int mid=left+(right-left+1)/2; //二分查找 if(matrix[floor][mid]<=target) left=mid; else right=mid-1; } while(floor<matrix.size()&&target>matrix[floor][right]) floor++; if(floor==matrix.size()) return false; if(matrix[floor][left]==target) return true; else return false; } };写法二:排除法
cppclass Solution { public: bool searchMatrix(vector<vector<int>>& matrix, int target) { int m = matrix.size(), n = matrix[0].size(); int i = 0, j = n - 1; while (i < m && j >= 0) { // 还有剩余元素 if (matrix[i][j] == target) { return true; // 找到 target } if (matrix[i][j] < target) { i++; // 这一行剩余元素全部小于 target,排除 } else { j--; // 这一列剩余元素全部大于 target,排除 } } return false; } };
7. 矩阵区域和⭐
1314. 矩阵区域和
https://leetcode.cn/problems/matrix-block-sum/
给你一个
m x n的矩阵mat和一个整数k,请你返回一个矩阵answer,其中每个answer[i][j]是所有满足下述条件的元素mat[r][c]的和:
i - k <= r <= i + k,j - k <= c <= j + k且(r, c)在矩阵内。
cppclass Solution { public: vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int K) { int m = mat.size(), n = mat[0].size(); vector<vector<int>> preadd(m+1,vector<int>(n+1,0)); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { preadd[i][j]=preadd[i-1][j]+preadd[i][j-1]-preadd[i-1][j-1]+mat[i-1][j-1]; } } vector<vector<int>> ans(m, vector<int>(n, 0)); for(int i=0;i<m;++i) { for(int j=0;j<n;j++) { // 计算左上角坐标 (row1, col1) 和右下角坐标 (row2, col2) int row1 = max(i - K, 0) + 1, col1 = max(j - K, 0) + 1; int row2 = min(i + K, m - 1) + 1, col2 = min(j + K, n - 1) + 1; ans[i][j]=preadd[row2][col2]+preadd[row1-1][col1-1]-preadd[row2][col1-1]-preadd[row1-1][col2]; } } return ans; } };注意:这里的二维下标逻辑很关键



