文章目录
-
-
- [238. 除自身以外数组的乘积](#238. 除自身以外数组的乘积)
- [41. 缺失的第一个正数](#41. 缺失的第一个正数)
- [73. 矩阵置零](#73. 矩阵置零)
-
238. 除自身以外数组的乘积
前缀积和后缀积
java
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] answer = new int[n];
int[] pre = new int[n];
int[] suf = new int[n];
pre[0] = nums[0];
suf[0] = nums[n - 1];
for(int i = 1;i < n;i++){
pre[i] = pre[i - 1] * nums[i];
suf[i] = suf[i - 1] * nums[n - 1 -i];
}
answer[0] = suf[n - 2];
answer[n - 1] = pre[n - 2];
for(int i = 1;i < n - 1;i++){
answer[i] = pre[i - 1]*suf[n - 1 - 1 - i];
}
return answer;
}
}
照灵茶山的优化一下索引
灵茶山版本的 suf[i] 直接表示"从 i+1 到 n-1 的积",索引清晰,无需转换
java
//灵茶山版
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] pre = new int[n];
pre[0] = 1; //初始化为1
for (int i = 1; i < n; i++) {
pre[i] = pre[i - 1] * nums[i - 1];
}
int[] suf = new int[n];
suf[n - 1] = 1;
for (int i = n - 2; i >= 0; i--) {
suf[i] = suf[i + 1] * nums[i + 1];
}
int[] ans = new int[n];
for (int i = 0; i < n; i++) {
ans[i] = pre[i] * suf[i];
}
return ans;
}
}
java
//个人改进版
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] answer = new int[n];
int[] pre = new int[n];
int[] suf = new int[n];
pre[0] = nums[0];
suf[n - 1] = nums[n - 1];
for(int i = 1;i < n;i++){
pre[i] = pre[i - 1] * nums[i];
}
for(int i = n - 2;i >= 0;i--){
suf[i] = suf[i + 1] * nums[i];
}
answer[0] = suf[1];
answer[n - 1] = pre[n - 2];
for(int i = 1;i < n - 1;i++){
answer[i] = pre[i - 1]*suf[i + 1];
}
return answer;
}
}
41. 缺失的第一个正数
原地哈希:将原来的数组视为哈希表
- 要找的数一定是在1,N+1里的整数
- 把1放在下标为0的位置上,把2放在下标为1的位置上...
java
class Solution {
public int firstMissingPositive(int[] nums) {
int n = nums.length;
for (int i = 0; i < n; i++) {
// 如果当前学生的学号在 [1,n] 中,但(真身)没有坐在正确的座位上
while (1 <= nums[i] && nums[i] <= n && nums[i] != nums[nums[i] - 1]) {
// 那么就交换 nums[i] 和 nums[j],其中 j 是 i 的学号
int j = nums[i] - 1; // 减一是因为数组下标从 0 开始
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
// 找第一个学号与座位编号不匹配的学生
for (int i = 0; i < n; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}
// 所有学生都坐在正确的座位上
return n + 1;
}
}
第一个for循环里面的while表示一直循环直到在i位置上的数回到它正确的位置或者它根本没位置
如果空间复杂度没要求 就用哈希表
javaclass Solution { public int firstMissingPositive(int[] nums) { int n = nums.length; Set<Integer>hashSet = new HashSet<>(); for(int num : nums){ hashSet.add(num); } for(int i = 1;i < n;i++){ if(!hashSet.contains(i)){ return i; } } return n + 1; } }
73. 矩阵置零
用两个标记数组分别记录每一行和每一列是否有零出现。
- 首先遍历该数组一次,如果某个元素为 0,那么就将该元素所在的行和列所对应标记数组的位置置为 true
- 最后再次遍历该数组,用标记数组更新原数组
java
class Solution {
public void setZeroes(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
boolean[] row = new boolean[m];
boolean[] col = new boolean[n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == 0) {
row[i] = col[j] = true;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (row[i] || col[j]) {
matrix[i][j] = 0;
}
}
}
}
}