9.23复习

This commit is contained in:
zhangsan 2025-09-23 20:55:16 +08:00
parent 5fd8c62f8a
commit 80302c704a
14 changed files with 131 additions and 40 deletions

View File

@ -16,7 +16,7 @@ import java.util.Arrays;
* 链接https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/
*/
//有点绕
//有点绕 简单
public class LargestSumAfterKNegations {
//让绝对值大的负数变为正数当前数值达到最大 那么如果将负数都转变为正数了K依然大于0 只找数值最小的正整数进行反转
public int largestSumAfterKNegations(int[] nums, int k) {

View File

@ -21,6 +21,7 @@ import java.util.List;
* 链接https://leetcode.cn/problems/lemonade-change/
*/
//二刷会做
public class LemonadeChange {
public boolean lemonadeChange(int[] bills) {
int five = 0; // 记录 5 美元的数量

View File

@ -12,6 +12,7 @@ package greedy;
* 链接https://leetcode.cn/problems/monotone-increasing-digits/
*/
//不会
//二刷不会
public class MonotoneIncreasingDigits {
/**
* 一旦发现某一位数字比右边一位大就必须在这一位或更靠左的一位上借位将该位数字减一而后面的所有位都置为 9以保证单调递增同时又尽可能大
@ -28,7 +29,7 @@ public class MonotoneIncreasingDigits {
// 1) 从右往左遇到下降就借位并记录位置
for (int i = d.length - 1; i > 0; --i) {
if (d[i-1] > d[i]) {
d[i-1]--; // 借位
d[i-1]--; // 借位 不可以是 d[i-1]=d[i] 比如5542正确的是4999 而不是3999
mark = i; // 标记后续全改成 9
}
}

View File

@ -21,6 +21,7 @@ import java.util.List;
* 链接https://leetcode.cn/problems/partition-labels/
*/
//二刷会做
//三刷会做
public class PartitionLabels {
/**
* 可以通过但是时间复杂度高

View File

@ -1,7 +1,9 @@
package greedy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* 题目 406. 根据身高重建队列 II (maxProfit)
@ -23,19 +25,36 @@ import java.util.LinkedList;
* 链接https://leetcode.cn/problems/queue-reconstruction-by-height/
*/
//不会 很妙
//二刷不会
public class ReconstructQueue {
/*
这道题最容易卡住的点是我们要满足每个人的 约束条件 (k )但约束条件依赖于前面的人互相影响
👉 正解的核心是 先处理高个子再插入矮个子
插入过程
插入 [7,0] [[7,0]]
插入 [7,1] [[7,0],[7,1]]
插入 [6,1] [[7,0],[6,1],[7,1]]
插入 [5,0] [[5,0],[7,0],[6,1],[7,1]]
插入 [5,2] [[5,0],[7,0],[5,2],[6,1],[7,1]]
插入 [4,4] [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
*/
public int[][] reconstructQueue(int[][] people) {
// 身高从大到小排身高相同k小的站前面
Arrays.sort(people, (a, b) -> {
if (a[0] == b[0]) return a[1] - b[1]; // a - b 是升序排列故在a[0] == b[0]的狀況下會根據k值升序排列
return b[0] - a[0]; //b - a 是降序排列在a[0] != b[0]的狀況會根據h值降序排列
if (a[0] == b[0]) return a[1] - b[1]; // 身高相同k小的排前面
return b[0] - a[0]; // 否则身高大的排前面
});
LinkedList<int[]> que = new LinkedList<>();
List<int[]> que = new ArrayList<>();
for (int[] p : people) {
que.add(p[1],p); //Linkedlist.add(index, value)會將value插入到指定index裡
que.add(p[1], p);
}
return que.toArray(new int[people.length][]);
int[][] res = new int[que.size()][];
for (int i = 0; i < que.size(); i++) {
res[i] = que.get(i);
}
return res;
//return que.toArray(new int[people.length][]);
}
}

View File

@ -20,13 +20,14 @@ package greedy;
* 链接https://leetcode.cn/problems/wiggle-subsequence/
*/
//不会 https://programmercarl.com/0376.%E6%91%86%E5%8A%A8%E5%BA%8F%E5%88%97.html
//二刷会做
public class WiggleMaxLength {
public int wiggleMaxLength(int[] nums) {
if (nums.length <= 1) {
return nums.length;
}
//当前差值
int curDiff = 0;
int curDiff;
//上一个差值
int preDiff = 0;
int count = 1;

View File

@ -13,6 +13,7 @@ package hash;
* 链接https://leetcode.cn/problems/ransom-note/
*/
//二刷会做
public class CanConstruct {
public boolean canConstruct(String ransomNote, String magazine) {
if (ransomNote.length() > magazine.length()) {

View File

@ -14,6 +14,7 @@ import java.util.Map;
* 链接https://leetcode.cn/problems/contains-duplicate-ii/
*/
//二刷会做
public class ContainsNearbyDuplicate {
public boolean containsNearbyDuplicate(int[] nums, int k) {
Map<Integer,Integer>map=new HashMap<>();

View File

@ -1,8 +1,6 @@
package hash;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
/**
* 题目 18. 四数之和 ( fourSum)
@ -19,6 +17,7 @@ import java.util.List;
* 链接https://leetcode.cn/problems/4sum/
*/
//二刷会做
public class FourSum {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
@ -66,5 +65,58 @@ public class FourSum {
}
return res;
}
//时间复杂度o(n^2) 哈希
public List<List<Integer>> fourSum2(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
if (n < 4) return res;
Arrays.sort(nums); // 先排序
// 哈希表存储每对两个数的和以及对应的索引
Map<Integer, List<int[]>> twoSumMap = new HashMap<>();
// 1. 先枚举所有的两数之和存入哈希表
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
int sum = nums[i] + nums[j];
if (!twoSumMap.containsKey(sum)) {
twoSumMap.put(sum, new ArrayList<>());
}
twoSumMap.get(sum).add(new int[]{i, j});
}
}
// 2. 枚举每对 i, j计算目标值 target - nums[i] - nums[j]
for (int i = 0; i < n - 3; i++) {
// 去重如果 nums[i] 和前一个 nums[i] 相同跳过
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < n - 2; j++) {
// 去重如果 nums[j] 和前一个 nums[j] 相同跳过
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
// 计算目标和
int remainingTarget = target - nums[i] - nums[j];
// 3. 查找两数之和为 remainingTarget 的组合
if (twoSumMap.containsKey(remainingTarget)) {
List<int[]> pairs = twoSumMap.get(remainingTarget);
for (int[] pair : pairs) {
int k = pair[0];
int l = pair[1];
// 确保所有的索引都不相同
if (k > j) {
List<Integer> quad = Arrays.asList(nums[i], nums[j], nums[k], nums[l]);
if (!res.contains(quad)) {
res.add(quad);
}
}
}
}
}
}
return res;
}
}

View File

@ -21,7 +21,7 @@ import java.util.Map;
* 链接https://leetcode.cn/problems/4sum-ii/
*/
//超时
//二刷不会
public class FourSumCount {
/**
* 思路把四数拆成两对 (A+B) (C+D)
@ -34,11 +34,6 @@ public class FourSumCount {
* 两个 n² 循环 O(n²)
* 空间复杂度
* 哈希表最多 n² 个键 O(n²)
* @param nums1
* @param nums2
* @param nums3
* @param nums4
* @return
*/
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {

View File

@ -16,6 +16,7 @@ import java.util.Arrays;
* 链接https://leetcode.cn/problems/non-overlapping-intervals/
*/
//不会
//二刷不会
public class EraseOverlapIntervals {
/**
* 1.按结束时间排序

View File

@ -18,6 +18,7 @@ import java.util.HashMap;
* 链接https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/
*/
//二刷会做
public class FindMinArrowShots {
/**
* 一种经典做法是先按照每个气球的 右端点 从小到大排序

View File

@ -17,6 +17,7 @@ import java.util.List;
* 链接https://leetcode.cn/problems/insert-interval/
*/
//想起来有点复杂
//二刷会做
public class Insert {
public int[][] insert(int[][] intervals, int[] newInterval) {
List<int[]> res = new ArrayList<>();
@ -42,8 +43,10 @@ public class Insert {
res.add(intervals[i]);
i++;
}
// 转回二维数组并返回
return res.toArray(new int[res.size()][]);
int[][]ress=new int[res.size()][];
for (int[] re : res) {
ress[i] = re;
}
return ress;
}
}

View File

@ -35,29 +35,43 @@ import java.util.List;
//二刷会做
public class ThreeSum {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans=new ArrayList<>();
List<List<Integer>> ans = new ArrayList<>();
// 1. 排序便于双指针和去重
Arrays.sort(nums);
for(int i=0;i<nums.length-2;i++){
if(nums[i]>0)break;
if(i>0 && nums[i]==nums[i-1])continue;
int j=i+1;
int k=nums.length-1;
int sum=nums[i]+nums[j]+nums[k];
while(j<k){
if(sum<0)j++;
else if(sum>0)k--;
else {
List<Integer> temp=new ArrayList<>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[k]);
ans.add(temp);
while(j<k && nums[k-1]==nums[k])k--; //或者用哈希去重
while(j<k && nums[j+1]==nums[j])j++;
k--;
// 2. 枚举第一个数 nums[i]
for (int i = 0; i < nums.length - 2; i++) {
// 如果第一个数已经大于 0后面不可能出现和为 0 的三元组
if (nums[i] > 0) break;
// 跳过重复的第一个数避免重复解
if (i > 0 && nums[i] == nums[i - 1]) continue;
int j = i + 1; // 左指针
int k = nums.length - 1; // 右指针
// 3. 双指针查找
while (j < k) {
int sum = nums[i] + nums[j] + nums[k];
if (sum < 0) {
j++; // 需要更大的数
} else if (sum > 0) {
k--; // 需要更小的数
} else {
// 找到一个三元组
ans.add(Arrays.asList(nums[i], nums[j], nums[k]));
// 跳过重复的 nums[j把左指针 j 移动到 最后一个相同元素的位置
while (j < k && nums[j] == nums[j + 1]) j++;
// 跳过重复的 nums[k]
while (j < k && nums[k] == nums[k - 1]) k--;
// 移动指针继续查找
j++;
k--;
}
sum=nums[i]+nums[j]+nums[k];
}
}
return ans;