6.15 二刷hot100 普通数组

This commit is contained in:
zhangsan 2025-06-15 10:02:13 +08:00
parent 46646daca0
commit 46a9f57fb2
3 changed files with 173 additions and 13 deletions

View File

@ -0,0 +1,58 @@
package array;
/**
* 题目41. 缺失的第一个正数 (firstMissingPositive)
* 描述给你一个未排序的整数数组 nums 请你找出其中没有出现的最小的正整数
*
* 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案
*
示例 1:
输入nums = [1,2,0]
输出3
解释范围 [1,2] 中的数字都在数组中
* 链接https://leetcode.cn/problems/first-missing-positive/description/
*/
//不会
public class FirstMissingPositive {
/**
* 定位阶段
* 遍历数组对每个元素 nums[i]如果它满足 1 nums[i] n且没有放在正确的位置上 nums[nums[i]1] nums[i]就把它和目标位置上的元素交换
*
* 这样做相当于把所有有可能成为第一个缺失正数的数放到它们理想的位置上
* 每个元素最多交换一次或两次因此这一阶段仍是 O(n)
* 检查阶段
* 再次遍历数组找到第一个下标 i使得 nums[i] i+1此时 i+1 就是缺失的最小正数
* 如果遍历结束都没发现不匹配的则说明 1n 都出现过答案是 n+1
*
* 为什么是常数空间
* 我们只是在原数组上做交换没有使用额外的数组或哈希表
* @param nums
* @return
*/
public int firstMissingPositive(int[] nums) {
int n = nums.length;
// 定位阶段把每个 1...n 的数放到下标 num-1
for (int i = 0; i < n; i++) {
// nums[i] 落在 [1, n] 且没有放在正确位置时交换到正确位置
while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
swap(nums, i, nums[i] - 1);
}
}
// 检查阶段第一个 nums[i] != i+1 的下标即答案
for (int i = 0; i < n; i++) {
if (nums[i] != i + 1) {
return i + 1;
}
}
// 全都对上了则缺失的是 n+1
return n + 1;
}
// 交换数组中两个元素
private void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}

View File

@ -16,24 +16,50 @@ package array;
输出: [0,0,9,0,0]
*/
//没做出来
//二刷不会
public class ProductExceptSelf {
/**
* 用一个数组 left 存储当前位置左侧所有元素的乘积left[0]=1每往右一步就把前一步的乘积乘上前一步的元素
* 用一个数组 right 存储当前位置右侧所有元素的乘积right[n-1]=1每往左一步就把后一步的乘积乘上后一步的元素
* 最终结果 res[i] = left[i] * right[i]既含括了除自身以外的所有元素
* 这样只需两次线性遍历时间 O(n)不使用除法若要 O(1) 额外空间可把前缀积直接存到结果数组再用一个变量累积后缀积
* @param nums
* @return
*/
public int[] productExceptSelf(int[] nums) {
int size=nums.length;
if(size==0)
return new int[]{};
int[] left=new int[size],right=new int[size];
left[0]=1;
right[size-1]=1;
int size = nums.length; // 数组长度
if (size == 0) // 如果输入数组为空
return new int[]{}; // 返回空数组
int[] left = new int[size], // left[i] nums[0..i-1] 的乘积
right = new int[size]; // right[i] nums[i+1..n-1] 的乘积
left[0] = 1; // 第一个元素左侧没有元素乘积为 1
right[size - 1] = 1; // 最后一个元素右侧没有元素乘积为 1
// 计算所有前缀积
for (int i = 1; i < size; i++) {
// left[i] = left[i-1] * nums[i-1]
// 即当前位置左侧乘积 = 前一个左侧乘积 × 前一个元素
left[i] = left[i - 1] * nums[i - 1];
}
// 计算所有后缀积
for (int j = size - 2; j >= 0; j--) {
// right[j] = right[j+1] * nums[j+1]
// 即当前位置右侧乘积 = 后一个右侧乘积 × 后一个元素
right[j] = right[j + 1] * nums[j + 1];
}
int[]res=new int[size];
int[] res = new int[size]; // 用于存放最终结果
// 合并前缀积和后缀积
for (int k = 0; k < size; k++) {
// 排除自身的所有元素乘积 = left[k] × right[k]
res[k] = left[k] * right[k];
}
return res;
return res; // 返回结果数组
}
}

View File

@ -15,8 +15,10 @@ import java.util.HashSet;
输入matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
*/
//二刷不会原地算法
public class SetZeroes {
public void setZeroes(int[][] matrix) {
//非原地算法
public void setZeroes1(int[][] matrix) {
int row=matrix.length;
int col=matrix[0].length;
HashSet<Integer>iset=new HashSet<>();
@ -40,4 +42,78 @@ public class SetZeroes {
}
}
}
/**
* 预处理第一行和第一列
* 遍历第一行看有没有 0记到布尔变量 firstRowZero
* 遍历第一列看有没有 0记到布尔变量 firstColZero
* 这样做是因为我们后面要把其余位置的标记都写到第一行/第一列上不能让原有的第 1 /1 列信息丢失
*
* 用第一行/列做标记
* (i=1,j=1) 开始遍历矩阵
* 如果 matrix[i][j] == 0则将 matrix[i][0] = 0标记该行要置零 matrix[0][j] = 0标记该列要置零
*
* 根据标记清零
* 再次遍历 (i=1,j=1) 区域
* 如果 matrix[i][0] == 0 matrix[0][j] == 0就把 matrix[i][j] 设为 0
*
* 处理第 1 行和第 1
* 如果 firstRowZero true就整行清 0
* 如果 firstColZero true就整列清 0
* @param matrix
*/
public void setZeroes(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
boolean firstRowZero = false;
boolean firstColZero = false;
// 1. 预处理第一行
for (int j = 0; j < n; j++) {
if (matrix[0][j] == 0) {
firstRowZero = true;
break;
}
}
// 1. 预处理第一列
for (int i = 0; i < m; i++) {
if (matrix[i][0] == 0) {
firstColZero = true;
break;
}
}
// 2. 用第一行/列做标记
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
// 3. 根据标记清零内部区域
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
// 4. 清零第一行如果需要
if (firstRowZero) {
for (int j = 0; j < n; j++) {
matrix[0][j] = 0;
}
}
// 4. 清零第一列如果需要
if (firstColZero) {
for (int i = 0; i < m; i++) {
matrix[i][0] = 0;
}
}
}
}