209. 长度最小的子数组
这里的更新结果就题来定
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int sum = 0;
int len = 0;
int f = 0;
for(int left = 0, right = 0; right < nums.length;){
//求和
sum += nums[right];
while(sum >= target){
//len
int t = right - left + 1;
if(f == 0 ){
len = t;
}
if(t < len ){
len = right - left +1;
}
f = 1;
left++;
// if(left >= nums.length){
// break;
// }
sum -= nums[left-1];
}
//if(right < nums.length){
right++;
//}
// if(left == nums.length){
// break;
// }
}
return len;
}
}
我在处理第一次len得到长度时使用的flag,老师用的时最大值,思路可以借鉴
先暴力枚举分析所有情况,做这种题都要这样。根据枚举优化得到滑动窗户做法
3. 无重复字符的最长子串
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set = new HashSet<Character>();
int n = s.length();
int len = 0;
for(int left = 0, right = 0; right < n;right++){
while(right > 0 && set.contains(s.charAt(right))){
set.remove(s.charAt(left));
left++;
}
set.add(s.charAt(right));
len = Math.max(len, right -left +1);
}
return len;
}
}
什么时候更新len有点难,多想一下过程的思路
这里用数组来当hash,空间复杂度为O(1),但如果new hash 就是O(N)
1004. 最大连续1的个数 III
虽然是两层循环,但时间复杂度时O(N),空间复杂度O(1)
1658. 将 x 减到 0 的最小操作数
class Solution {
public int minOperations(int[] nums, int x) {
int s= 0;
for(int i = 0; i< nums.length; i++){
s += nums[i];
}
int target = s - x, len = 0;
if(target == 0){
return nums.length;
}
if(target < 0){
return -1;
}
int f = 0;
for(int left = 0, right = 0, sum = 0; right < nums.length; right++ ){
sum += nums[right];
while(sum >= target){
if(sum == target){
len = Math.max(len, right - left + 1);
sum -= nums[left];
left++;
f = 1;
}else{
sum -= nums[left];
left++;
}
}
}
return f == 1 ? nums.length - len : -1;
}
}
如果数组中有0 负数就不能用滑动窗口
904. 水果成篮
class Solution {
public static int totalFruit(int[] fruits) {
Map<Integer,Integer> hasH = new HashMap<Integer,Integer>();
int len = 0;
for(int left = 0, right = 0; right < fruits.length; right++){
hasH.put(fruits[right],hasH.getOrDefault(fruits[right],0)+1);
while(hasH.size() > 2){
hasH.put(fruits[left],hasH.getOrDefault(fruits[left],0)-1);
left++;
if(hasH.get(fruits[left-1]) == 0){
hasH.remove(fruits[left-1]);
}
}
if(hasH.size() <= 2){
len = Math.max(len,right - left +1);
}
}
return len;
}
}
因为水果的范围没有超过int 可以使用数组,这样减少队Hash的调用,时间复杂度会大大的变小
438. 找到字符串中所有字母异位词
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> List = new ArrayList<>();
int[] HashP = new int[26];
int l = p.length();
if(s.length() < p.length()){
return List;
}
for(int i = 0 ; i < p.length(); i++){
HashP[p.charAt(i) - 97]++;
}
int count = 0;
int[] HashS = new int[26];
for(int left = 0, right = 0; right < s.length(); right++){
while (count < l){
HashS[s.charAt(right)-97]++;
count++;
if(count == l){
break;
}
right++;
}
int f = 1;
for (int j = 0; j < 26; j++){
if(HashS[j] != HashP[j]){
f = 0;
break;
}
}
if( f == 0){
HashS[s.charAt(left)-97]--;
count--;
left++;
}else {
List.add(left);
HashS[s.charAt(left)-97]--;
count--;
left++;
}
}
return List;
}
}
复盘:
第一次:
class Solution {
public List<Integer> findAnagrams(String ss, String pp) {
List<Integer> ret = new ArrayList<>();
char[] s = ss.toCharArray();
char[] p = pp.toCharArray();
//new pp Hash1
int[] Hash1 = new int[26];
int kinds = 0;
for(char ch: p){
if(Hash1[ch-97] == 0){
kinds++;
}
Hash1[ch-97]++;
}
//窗口长度
int len = pp.length();
int[] Hash2 = new int[26];
//窗口中有效字符个数
int count = 0;
for(int left = 0, right = 0; right < ss.length(); right++){
//入窗口 in 种类
char in = ss.charAt(right);
Hash2[in - 97]++;
if(Hash2[in - 97] <= Hash1[in - 97]){
count++;
}
//判断
while(right - left + 1 >= len){
if(count == pp.length() && right -left + 1 == len){
ret.add(left);
}
//出窗口 Hash[left]--; left ++
char out = ss.charAt(left);
if(Hash2[out - 97] <= Hash1[out - 97]){
count--;
}
Hash2[out - 97]--;
left++;
}
}
return ret;
}
}
30. 串联所有单词的子串
复盘:
第一次:
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> ret = new ArrayList<>();
Map<String,Integer> Hash1 = new HashMap<>();
for(String str: words){
Hash1.put(str,Hash1.getOrDefault(str,0)+1);//存储words
}
// 字符上总长度 单个字符串长度
int L = words.length,len = words[0].length();
for(int i = 0; i < len; i++){
Map<String,Integer> Hash2 = new HashMap<>();
int count = 0;
for(int left = i, right = i; right <= s.length() - len; right += len){
//进窗口
String in = s.substring(right,right+len);
Hash2.put(in,Hash2.getOrDefault(in,0)+1);
if(Hash2.get(in) <= Hash1.getOrDefault(in,0)){
count++;
}
//判断
//更新
//出窗口
while(right + len - left >= L*len){
if(L == count && right + len - left == L*len){
ret.add(left);
}
String out = s.substring(left,left+len);
if(Hash2.get(out) <= Hash1.getOrDefault(out,0)){
count--;
}
Hash2.put(out,Hash2.get(out)-1);
left += len;
}
}
}
return ret;
}
}
right是截取的边界,所以要加=
76. 最小覆盖子串
class Solution {
public String minWindow(String ss, String tt) {
String ret = "";
char[] s = ss.toCharArray();
char[] t =tt.toCharArray();
if(ss.length() < tt.length()){
return ret;
}
Map<Character,Integer> Hash1 = new HashMap<>();//存储tt
for(char str : t){
Hash1.put(str,Hash1.getOrDefault(str,0)+1);
}
Map<Character,Integer> Hash2 = new HashMap<>();//窗口
int count = 0; //容器有效的
int f = 0;
for(int left = 0, right = 0; right < s.length; right++){//进窗口 维护 count
char in = s[right];
Hash2.put(in,Hash2.getOrDefault(in,0)+1);
if(Hash2.get(in) == Hash1.getOrDefault(in,0)) {
count++;
}
//判断
while(count == Hash1.size()){
//更新 subString
if(ss.substring(left,right+1).length() < ret.length() && f == 1){
ret = ss.substring(left,right+1);
}else if(f == 0){
f = 1;
ret = ss.substring(left,right+1);
}
//出窗口 维护count
char out = s[left];
if(Hash2.get(out) == Hash1.getOrDefault(out,0)){
count--;
}
Hash2.put(out,Hash2.get(out)-1);
left++;
}
}
return ret;
}
}
class Solution {
public String minWindow(String ss, String tt) {
String ret = "";
char[] s = ss.toCharArray();
char[] t = tt.toCharArray();
int[] Hash1 = new int[128];//记录tt
int[] Hash2 = new int[128];//窗口
//记录tt中的字符 //记录字符的种类
int kinds = 0;
for(char str: t){
if(Hash1[str] == 0)kinds++;
Hash1[str]++;
}
int f = 0,count = 0;
for(int left = 0, right = 0; right < ss.length(); right++){
//进窗口 //种类
int in = s[right];
Hash2[in]++;
if(Hash2[in] == Hash1[in]) count++;
//判断//更新//出窗口
while(count == kinds){
if(ss.substring(left,right+1).length() < ret.length() && f == 1){
ret = ss.substring(left,right+1);
}else if(f == 0){
f = 1;
ret = ss.substring(left,right+1);
}
int out = s[left];
if(Hash2[out] == Hash1[out]) count--;
Hash2[out]--;
left++;
}
}
return ret;
}
}