6.11 二刷hot100 哈希+双指针

This commit is contained in:
zhangsan 2025-06-11 10:48:25 +08:00
parent a26333688a
commit d3cfe89d74
6 changed files with 88 additions and 8 deletions

View File

@ -25,6 +25,7 @@ import java.util.List;
*/ */
//做出来了 //做出来了
//二刷会做
public class GroupAnagrams { public class GroupAnagrams {
//计数 //计数
public List<List<String>> groupAnagrams1(String[] strs) { public List<List<String>> groupAnagrams1(String[] strs) {

View File

@ -23,6 +23,7 @@ import java.util.HashSet;
输出3 输出3
*/ */
//没做出来 //没做出来
//二刷会做
public class LongestConsecutive { public class LongestConsecutive {
public int longestConsecutive(int[] nums) { public int longestConsecutive(int[] nums) {
// 将数组中的所有元素存入 HashSet // 将数组中的所有元素存入 HashSet

View File

@ -15,8 +15,9 @@ import java.util.LinkedList;
* 链接https://leetcode.cn/problems/trapping-rain-water/ * 链接https://leetcode.cn/problems/trapping-rain-water/
*/ */
//困难题 不会 //困难题 不会
//二刷不会
public class Trap { public class Trap {
//暴力解法 //暴力解法 竖着收集雨水
public int trap1(int[] height) { public int trap1(int[] height) {
int sum = 0; int sum = 0;
for (int i = 0; i < height.length; i++) { for (int i = 0; i < height.length; i++) {
@ -24,21 +25,35 @@ public class Trap {
if (i == 0 || i == height.length - 1) { if (i == 0 || i == height.length - 1) {
continue; continue;
} }
/**
* 目的对于每一个柱子 i想知道它左右两边的最高柱子分别是多少
*
* 因为要接雨水关键在于当前位置能接多少水取决于
*
* 它左边的最高柱子
* 它右边的最高柱子
* 当前柱子的高度
*
*
*/
int rHeight = height[i]; // 初始化右边最大高度为当前位置高度后面会尝试找更高的
int lHeight = height[i]; // 初始化左边最大高度为当前位置高度后面会尝试找更高的
int rHeight = height[i]; // 记录右边柱子的最高高度 // 从当前位置 i 向右扫描找出右侧最高的柱子高度
int lHeight = height[i]; // 记录左边柱子的最高高度
for (int r = i + 1; r < height.length; r++) { for (int r = i + 1; r < height.length; r++) {
if (height[r] > rHeight) { if (height[r] > rHeight) {
rHeight = height[r]; rHeight = height[r]; // 更新右侧最高高度
} }
} }
// 从当前位置 i 向左扫描找出左侧最高的柱子高度
for (int l = i - 1; l >= 0; l--) { for (int l = i - 1; l >= 0; l--) {
if (height[l] > lHeight) { if (height[l] > lHeight) {
lHeight = height[l]; lHeight = height[l]; // 更新左侧最高高度
} }
} }
int h = Math.min(lHeight, rHeight) - height[i]; int h = Math.min(lHeight, rHeight) - height[i];
if (h > 0) { if (h > 0) {
sum += h; sum += h;
@ -46,7 +61,19 @@ public class Trap {
} }
return sum; return sum;
} }
//动态规划 //动态规划 竖着收集雨水
/**
* 对于每一个柱子 i接雨水的能力取决于它左右两边最高柱子的最小值
* 因此预先构造两个数组
* maxLeft[i] 表示从左到 i 的最大值
* maxRight[i] 表示从右到 i 的最大值
* 然后遍历每一个柱子除了两端计算
* Math.min(maxLeft[i - 1], maxRight[i + 1]) - height[i]
*
* @param height
* @return
*/
public int trap2(int[] height) { public int trap2(int[] height) {
if (height.length <= 2) return 0; if (height.length <= 2) return 0;
int n = height.length; int n = height.length;
@ -76,7 +103,54 @@ public class Trap {
return sum; return sum;
} }
//单调栈 //双指针 竖着收集雨水
/**
* 左右各有一个指针从两端向中间走
* leftMax rightMax 分别记录从左右遇到的最高柱子
* 每次比较 height[left] height[right]
* 谁矮就处理谁因为能接水的高度取决于当前方向上历史最高柱子
* 用双指针减少了空间整体时间仍然是 O(n)
* @param height
* @return
*/
public int trap3(int[] height) {
int left = 0, right = height.length - 1;
int leftMax = 0, rightMax = 0;
int sum = 0;
while (left < right) {
if (height[left] < height[right]) {
if (height[left] > leftMax) {
leftMax = height[left];
} else {
sum += leftMax - height[left];
}
left++;
} else {
if (height[right] >= rightMax) {
rightMax = height[right];
} else {
sum += rightMax - height[right];
}
right--;
}
}
return sum;
}
//单调栈 横着收集雨水
/**
* 使用一个单调递减栈存的是索引遇到比栈顶高的柱子就说明可以接水了
* 每当当前柱子比栈顶柱子高就弹出栈顶作为凹槽底部
* 然后新的栈顶变成左边界当前柱子是右边界
* 这三者一起决定了可以接的水量
* distance = i - stack.peek() - 1
* height = min(height[i], height[stack.peek()]) - height[top]
*
* 遇到不能接水的就把当前柱子索引压入栈中等待后面的柱子来形成边界
* @param height
* @return
*/
public int trap(int[] height) { public int trap(int[] height) {
int sum = 0; int sum = 0;
Deque<Integer> stack = new LinkedList<>(); Deque<Integer> stack = new LinkedList<>();

View File

@ -16,6 +16,8 @@ package twopointers;
输入height = [1,1] 输入height = [1,1]
输出1 输出1
*/ */
//一刷不会
//二刷会做
public class MaxArea { public class MaxArea {
//暴力解法O(N^2) 没过所有例子 //暴力解法O(N^2) 没过所有例子

View File

@ -14,6 +14,7 @@ package twopointers;
输出: [0] 输出: [0]
*/ */
//做出了但时间复杂度O(N^2) //做出了但时间复杂度O(N^2)
//二刷会做 时间复杂度on
public class MoveZeroes { public class MoveZeroes {
public void moveZeroes1(int[] nums) { public void moveZeroes1(int[] nums) {
for (int i = 0; i < nums.length; i++) { for (int i = 0; i < nums.length; i++) {

View File

@ -32,6 +32,7 @@ import java.util.List;
*/ */
//做出来了 //做出来了
//二刷会做
public class ThreeSum { public class ThreeSum {
public List<List<Integer>> threeSum(int[] nums) { public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans=new ArrayList<>(); List<List<Integer>> ans=new ArrayList<>();