leetcode刷题(七)

技巧
  • 滑动窗口
  • 左闭右开区间[left,right)
void slidingWindow(String s){
   HashMap<Character,Integer>window=new HashMap<>();
   int left=0,right=0;
   while (right<s.length()){
       char c=s.charAt(right);
       right++;
       // 扩大窗口
       window.put(c,window.getOrDefault(c,0)+1);
       // debug
       System.out.printf("window: [%d, %d)\n", left, right);
       // ... 更新操作
       while (left<right)// 达到需要缩小窗口的条件
       {
           char d=s.charAt(left);
           left++;
           window.put(d,window.get(d)-1);
           // ... 更新操作
       }
  }
}

最小覆盖子串
在这里插入图片描述

思路
  1. 定义一个哈希表need和window,need用来存储子串t的字符和字符出现的次数,window用来存储串s中子串t的字符和出现次数
  2. 按照滑动窗口算法框架:
    (1)遍历串s, 扩大窗口right++
    (2)当窗口window中各个字符出现次数达到need中个字符出现次数的要求时,缩小窗口left++
    (3)选择覆盖子串t的最小窗口长度更新len(right-left<len就更新)
public static String minWindow(String s, String t) {
  HashMap<Character,Integer>window=new HashMap<>();
  HashMap<Character,Integer>need=new HashMap<>();
  int left=0,right=0,valid=0,start=0,len=Integer.MAX_VALUE;
  for(char c:t.toCharArray()){
      need.put(c,need.getOrDefault(c,0)+1);
  }
  while (right<s.length()){
      char c=s.charAt(right);
      right++;
      if(need.containsKey(c)){
          window.put(c,window.getOrDefault(c,0)+1);
          if(need.get(c).equals(window.get(c))){
              valid++;
          }
      }
      if(valid==need.size())
          System.out.printf("window: [%d, %d)\n", left, right);
      while (valid==need.size()){
          if(right-left<len){
              start=left;
              len=right-left;
          }
          char d=s.charAt(left);
          left++;
          if(need.containsKey(d)){
              if(need.get(d).equals(window.get(d)))
                  valid--;
              window.put(d,window.getOrDefault(d,0)-1);
          }
      }
  }
  return len==Integer.MAX_VALUE?"":s.substring(start,start+len);
}

字符串的排列
在这里插入图片描述

思路
  1. 定义一个哈希表need和window,need用来存储子串s1的字符和字符出现的次数,window用来存储串s2中子串s1的字符和出现次数
  2. 按照滑动窗口算法框架:
    (1)遍历串s2, 扩大窗口right++
    (2)当窗口长度达到字符串s1的长度(大于等于),缩小窗口
    (3)如果window中出现的字符和次数与need都能对得上,返回true
public boolean checkInclusion(String s1, String s2) {
    HashMap<Character,Integer>need=new HashMap<>();
    HashMap<Character,Integer>window=new HashMap<>();
    int left=0,right=0,valid=0;
    for(char c:s1.toCharArray()){
        need.put(c,need.getOrDefault(c,0)+1);
    }
    while (right<s2.length()){
        char c=s2.charAt(right);
        right++;
        if(need.containsKey(c)){
            window.put(c,window.getOrDefault(c,0)+1);
            if(window.get(c).equals(need.get(c)))
                valid++;
        }
        while (right-left>=s1.length()){
            if(valid==need.size())
                return true;
            char d=s2.charAt(left);
            left++;
            if(need.containsKey(d)){
                if(need.get(d).equals(window.get(d)))
                    valid--;
                window.put(d,window.get(d)-1);
            }
        }
    }
    return false;
 }

找到字符串中所有字母的异位词

在这里插入图片描述

思路

和上一题同样的思路,使用List存储符合条件的子串起始索引

public List<Integer> findAnagrams(String s, String p) {
    List<Integer>res=new ArrayList<>();
    HashMap<Character,Integer>need=new HashMap<>();
    HashMap<Character,Integer>window=new HashMap<>();
    int left=0,right=0,valid=0;
    for(char c:p.toCharArray()){
        need.put(c,need.getOrDefault(c,0)+1);
    }
    while (right<s.length()){
        char c=s.charAt(right);
        right++;
        if(need.containsKey(c)){
            window.put(c,window.getOrDefault(c,0)+1);
            if(need.get(c).equals(window.get(c)))
                valid++;
        }
        while (right-left>=p.length()){
            if(valid==need.size()){
                res.add(left);
            }
            char d=s.charAt(left);
            left++;
            if(need.containsKey(d)){
                if(need.get(d).equals(window.get(d)))
                    valid--;
                window.put(d,window.get(d)-1);
            }
        }
    }
    return res;
}

无重复的最长子串
在这里插入图片描述

思路
  1. 使用哈希表window存储串s中字符和字符出现的次数
  2. 按照滑动窗口算法框架
    (1)遍历串s,扩大窗口,right++
    (2)当前字符在哈希表中出现次数大于1时,说明需要缩小窗口,left++
    (3)记录最大的right-left差值更新结果
public int lengthOfLongestSubstring(String s) {
	 HashMap<Character,Integer>window=new HashMap<>();
	 int left=0,right=0,max_len=0;
	 while (right<s.length()){
	     char c=s.charAt(right);
	     right++;
	     window.put(c,window.getOrDefault(c,0)+1);
	     while (window.get(c)>1){
	         char d=s.charAt(left);
	         left++;
	         window.put(d,window.get(d)-1);
	     }
	     max_len=Math.max(max_len,right-left);
	 }
	 return max_len;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值