6.13 二刷hot100 子串+普通数组

This commit is contained in:
zhangsan 2025-06-13 18:31:47 +08:00
parent 97564746ff
commit 46646daca0
4 changed files with 128 additions and 5 deletions

View File

@ -18,6 +18,7 @@ package array;
输出23 输出23
*/ */
//二刷会做
public class MaxSubArray { public class MaxSubArray {
public int maxSubArray(int[] nums) { public int maxSubArray(int[] nums) {
int tempsum=nums[0],maxsum=nums[0]; int tempsum=nums[0],maxsum=nums[0];
@ -31,6 +32,7 @@ public class MaxSubArray {
return maxsum; return maxsum;
} }
//假设还要同时返回起始结束下标 //假设还要同时返回起始结束下标
//[-2,1,-3,4,-1,2,1,-5,4]
public int[] maxSubArray2(int[] nums) { public int[] maxSubArray2(int[] nums) {
int tempsum = nums[0]; // 当前子数组的和 int tempsum = nums[0]; // 当前子数组的和
int maxsum = nums[0]; // 最大子数组和 int maxsum = nums[0]; // 最大子数组和

View File

@ -20,13 +20,13 @@ import java.util.List;
输出[[1,5]] 输出[[1,5]]
解释区间 [1,4] [4,5] 可被视为重叠区间 解释区间 [1,4] [4,5] 可被视为重叠区间
*/ */
//二刷会做
public class Merge { public class Merge {
public int[][] merge(int[][] intervals) { public int[][] merge(int[][] intervals) {
Arrays.sort(intervals,(a,b)->{ Arrays.sort(intervals,(a,b)->{
if(a[0]!=b[0]){ if(a[0]!=b[0])
return a[0]-b[0]; return a[0]-b[0];
}else else
return a[1]-b[1]; return a[1]-b[1];
}); });
List<int[]>merged=new ArrayList<>(); List<int[]>merged=new ArrayList<>();

View File

@ -19,9 +19,9 @@ package array;
向右轮转 1 : [99,-1,-100,3] 向右轮转 1 : [99,-1,-100,3]
向右轮转 2 : [3,99,-1,-100] 向右轮转 2 : [3,99,-1,-100]
*/ */
//二刷会做
public class RotateArray { public class RotateArray {
public void rotateArray(int[] nums, int k) { public void rotateArray2(int[] nums, int k) {
int cnt=nums.length,index=0; int cnt=nums.length,index=0;
int offset=k%cnt; int offset=k%cnt;
int[]temp=new int[k]; int[]temp=new int[k];
@ -36,4 +36,27 @@ public class RotateArray {
nums[i]=temp[i]; nums[i]=temp[i];
} }
} }
public void rotateArray(int[] nums, int k) {
int n = nums.length;
k %= n; // 防止 k > n
if (k == 0) return;
// 1. 整体翻转 [0, n-1]
reverse(nums, 0, n - 1);
// 2. k 个翻转 [0, k-1]
reverse(nums, 0, k - 1);
// 3. 剩余部分翻转 [k, n-1]
reverse(nums, k, n - 1);
}
// 原地翻转 helper
private void reverse(int[] a, int i, int j) {
while (i < j) {
int tmp = a[i];
a[i++] = a[j];
a[j--] = tmp;
}
}
} }

View File

@ -0,0 +1,98 @@
package substring;
import java.util.Arrays;
import java.util.HashMap;
/**
* 题目76. 最小覆盖子串 (minWindow)
* 描述给你一个字符串 s 一个字符串 t 返回 s 中涵盖 t 所有字符的最小子串如果 s 中不存在涵盖 t 所有字符的子串则返回空字符串 ""
* 注意
*
* 对于 t 中重复字符我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量
* 如果 s 中存在这样的子串我们保证它是唯一的答案
*
* 链接https://leetcode.cn/problems/minimum-window-substring/
*
示例 1
输入s = "ADOBECODEBANC", t = "ABC"
输出"BANC"
解释最小覆盖子串 "BANC" 包含来自字符串 t 'A''B' 'C'
*/
//不会
public class MinWindow {
/**
*滑动窗口的核心是用两根指针 lr s 上维护一个区间既能又能保证它包含 t 中所有字符且最小
*
* 用数组 need[128] 记录 t 中每个字符的需求次数window[128] 记录当前窗口中的次数valid 记录满足需求的字符种类数
* 右指针 r 向右滑遇到 need[s[r]]>0 时增加 window[s[r]] window[s[r]]==need[s[r]] valid++
* valid == 需要的字符种类数 可尝试用左指针 l 收缩窗口
* 更新最小长度
* 若移出字符 d=s[l] need[d]>0window[d]-- window[d]<need[d] valid--
* l++
* 重复 23直至 r 到末尾
* @param s
* @param t
* @return
*/
public String minWindow(String s, String t) {
// 边界检查
if (s == null || t == null || s.length() < t.length()) {
return "";
}
// 1. 准备 need window 两个计数器
int[] need = new int[128];
int[] window = new int[128];
for (char c : t.toCharArray()) {
need[c]++;
}
int required = 0; // 需要满足的不同字符种类数
for (int cnt : need) {
if (cnt > 0) required++;
}
// 2. 初始化窗口左右边界已满足种类数最优结果
int left = 0, right = 0;
int valid = 0;
int start = 0, minLen = Integer.MAX_VALUE;
// 3. 开始滑动右边界
while (right < s.length()) {
char c = s.charAt(right);
right++;
// 如果是目标字符则更新 window 计数且可能增加 valid
if (need[c] > 0) {
window[c]++;
if (window[c] == need[c]) {
valid++;
}
}
// 4. 当所有字符需求都已满足时尝试收缩左边界
while (valid == required) {
// 更新最小覆盖子串
if (right - left < minLen) {
start = left;
minLen = right - left;
}
// d 是将移出窗口的字符
char d = s.charAt(left);
left++;
if (need[d] > 0) {
//因为window[d]的数量可能>need[d]的数量减掉一个还是valid
if (window[d] == need[d]) {
valid--;
}
window[d]--;
}
}
}
// 5. 返回结果
return minLen == Integer.MAX_VALUE
? ""
: s.substring(start, start + minLen);
}
}