6.13 二刷hot100 子串+普通数组
This commit is contained in:
parent
97564746ff
commit
46646daca0
@ -18,6 +18,7 @@ package array;
|
||||
输出:23
|
||||
|
||||
*/
|
||||
//二刷会做
|
||||
public class MaxSubArray {
|
||||
public int maxSubArray(int[] nums) {
|
||||
int tempsum=nums[0],maxsum=nums[0];
|
||||
@ -31,6 +32,7 @@ public class MaxSubArray {
|
||||
return maxsum;
|
||||
}
|
||||
//假设还要同时返回起始结束下标:
|
||||
//[-2,1,-3,4,-1,2,1,-5,4]
|
||||
public int[] maxSubArray2(int[] nums) {
|
||||
int tempsum = nums[0]; // 当前子数组的和
|
||||
int maxsum = nums[0]; // 最大子数组和
|
||||
|
@ -20,13 +20,13 @@ import java.util.List;
|
||||
输出:[[1,5]]
|
||||
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
|
||||
*/
|
||||
|
||||
//二刷会做
|
||||
public class Merge {
|
||||
public int[][] merge(int[][] intervals) {
|
||||
Arrays.sort(intervals,(a,b)->{
|
||||
if(a[0]!=b[0]){
|
||||
if(a[0]!=b[0])
|
||||
return a[0]-b[0];
|
||||
}else
|
||||
else
|
||||
return a[1]-b[1];
|
||||
});
|
||||
List<int[]>merged=new ArrayList<>();
|
||||
|
@ -19,9 +19,9 @@ package array;
|
||||
向右轮转 1 步: [99,-1,-100,3]
|
||||
向右轮转 2 步: [3,99,-1,-100]
|
||||
*/
|
||||
|
||||
//二刷会做
|
||||
public class RotateArray {
|
||||
public void rotateArray(int[] nums, int k) {
|
||||
public void rotateArray2(int[] nums, int k) {
|
||||
int cnt=nums.length,index=0;
|
||||
int offset=k%cnt;
|
||||
int[]temp=new int[k];
|
||||
@ -36,4 +36,27 @@ public class RotateArray {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
98
src/main/java/substring/MinWindow.java
Normal file
98
src/main/java/substring/MinWindow.java
Normal 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 {
|
||||
/**
|
||||
*滑动窗口的核心是:用两根指针 l、r 在 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]>0,window[d]--,若 window[d]<need[d] 则 valid--;
|
||||
* l++。
|
||||
* 重复 2–3,直至 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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user