其他分享
首页 > 其他分享> > LeetCode刷题笔记—滑动窗口与哈希表(3.无重复字符的最长子串、567.字符串的排列)

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