LeetCode刷题笔记—滑动窗口与哈希表(3.无重复字符的最长子串、567.字符串的排列)
作者:互联网
3. 无重复字符的最长子串(难度:中等)
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2: 输入: s = "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 示例 3: 输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 示例 4: 输入: s = "" 输出: 0 提示: 0 <= s.length <= 5 * 104 s 由英文字母、数字、符号和空格组成
思路:
图片来自:【无重复字符的最长子串】滑动窗口,精简代码,图解模拟 - 无重复字符的最长子串 - 力扣(LeetCode) (leetcode-cn.com)
将滑动窗口中没有重复的字符串放入哈希表中,然后移动右边界,若没有重复字符,则将哈希表不断更新,每次移动边界后都会进行一次比较来存储长度最大值。当遇到重复字符,调整左边界(哈希表也在不断缩短),直至此时哈希表中不在存在重复字符,然后重复以上步骤直至结束。
代码:
class Solution { public int lengthOfLongestSubstring(String s) { HashSet<Character> map = new HashSet<Character>(); int n = s.length(),r = -1,ans = 0; for(int i = 0;i<n;i++){ if(i!=0){//遇到重复字符,调整左边界 map.remove(s.charAt(i - 1)); } while(r < n - 1 && !map.contains(s.charAt(r + 1))){ //移动右边界 map.add(s.charAt(r + 1)); ++r; } ans = Math.max(ans,r - i + 1);//移动边界后都会进行一次比较来存储长度最大值 } return ans; } }
567. 字符串的排列(难度:中等)
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。 换句话说,s1 的排列之一是 s2 的 子串 。 示例 1: 输入:s1 = "ab" s2 = "eidbaooo" 输出:true 解释:s2 包含 s1 的排列之一 ("ba"). 示例 2: 输入:s1= "ab" s2 = "eidboaoo" 输出:false 提示: 1 <= s1.length, s2.length <= 104 s1 和 s2 仅包含小写字母
思路:记录s1中字符种类和出现次数,运用滑动窗口和s2比较,当滑动窗口中出现的字符种类数和 s1 中出现的字符种类数相等和对应次数相等,并且 s2 上的滑动窗口的长度等于字符串 s1 的长度的时候,就找到了 s1 的一个排列。
代码:
class Solution { public boolean checkInclusion(String s1, String s2) { char[] pattern = s1.toCharArray(); char[] text = s2.toCharArray(); int pLen = s1.length(); int tLen = s2.length(); //s1和s2中字符对应出现的次数 int[] pFreq = new int[26]; int[] winFreq = new int[26]; //扫描s1,统计各个字符出现的频数 for (int i = 0; i < pLen; i++) { pFreq[pattern[i] - 'a']++; } //表示在s1中出现的字符的种类数 int pCount = 0; for (int i = 0; i < 26; i++) { if (pFreq[i] > 0){ pCount++; } } //声明滑动窗口两个滑动变量 int left = 0; int right = 0; //当滑动窗口中的某个字符个数与 s1 中对应相等的时候才计数 //滑动窗口中和s1相同的字符种类数:winCount int winCount = 0; while (right < tLen){ if (pFreq[text[right] - 'a'] > 0 ) { winFreq[text[right] - 'a']++; if (winFreq[text[right] - 'a'] == pFreq[text[right] - 'a']){ winCount++; } } right++; while (pCount == winCount){ if (right - left == pLen){ return true; } //e i d b a o o o if (pFreq[text[left] - 'a'] > 0 ) { winFreq[text[left] - 'a']--; if (winFreq[text[left] - 'a'] < pFreq[text[left] - 'a']){ winCount--; } } left++; } } return false; } }
标签:子串,字符,int,s2,s1,567,哈希,text,LeetCode 来源: https://www.cnblogs.com/Noob-Green-Hand/p/15164297.html