9.23复习
This commit is contained in:
parent
5fd8c62f8a
commit
80302c704a
@ -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) {
|
||||
|
||||
@ -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 美元的数量
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import java.util.List;
|
||||
* 链接:https://leetcode.cn/problems/partition-labels/
|
||||
*/
|
||||
//二刷会做
|
||||
//三刷会做
|
||||
public class PartitionLabels {
|
||||
/**
|
||||
* 可以通过,但是时间复杂度高!
|
||||
|
||||
@ -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][]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -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<>();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ import java.util.Arrays;
|
||||
* 链接:https://leetcode.cn/problems/non-overlapping-intervals/
|
||||
*/
|
||||
//不会
|
||||
//二刷不会
|
||||
public class EraseOverlapIntervals {
|
||||
/**
|
||||
* 1.按结束时间排序
|
||||
|
||||
@ -18,6 +18,7 @@ import java.util.HashMap;
|
||||
|
||||
* 链接:https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/
|
||||
*/
|
||||
//二刷会做
|
||||
public class FindMinArrowShots {
|
||||
/**
|
||||
* 一种经典做法是:先按照每个气球的 右端点 从小到大排序;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user