3.无重复字符的最长字串

题目链接

双指针


在题目中要求找出最长的无重复字串,重要的是不重不漏的找到所有的子串,然后找到字串中字符不重复的子串,最后在这些不重复字符的子串中找到长度最长的一个。可以以下标 \(i\) 为尾字符分为一类子串,那么只需要找到一个尽可能小的 \(j\) ,即长度最大, \([j, i]\) 这一段子串就是以\(i\)结尾的最长不重复子串(故后续枚举每一类即可)。
现在考虑一个问题,当我们的\(i\)进行移动的时候变为 \(i^,\) ,我们的 \(j^,\)一定是小于等于 \(j\) , 可以使用反证法证明。所以后续类别(以\(i^,\)为尾字符)的不重复子串的窗口左边界要么不移动,要么向右移动,所以可以使用一个哈希表来维护 \([j, i]\) 之间的字符出现的数量,每次 \(i\) 移动的时候,判定 \(j\) 应该移动到什么地方,会使得该窗口中不存在重复字符,取每一类中最长不重复子串的最大值即可。
因为两个指针最多遍历一遍数组,所以时间复杂度为:O(n)

CPP

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> heap;
        int res = 0;
        for(int i = 0, j = 0; i < s.size(); ++ i){
           heap[s[i]] ++;
           while(heap[s[i]] > 1) heap[s[j ++]] --;
           res = max(res, i - j + 1);
        }

        return res;
    }
};

Java

class Solution {
    public int lengthOfLongestSubstring(String s) {
        HashMap<Character, Integer> heap = new HashMap<>();
        int res = 0;
        char[] cs = s.toCharArray();
        for(int i = 0, j = 0; i < cs.length; ++ i){
            heap.put(cs[i], heap.getOrDefault(cs[i], 0) + 1);
            while(heap.getOrDefault(cs[i], 0) > 1) heap.put(cs[j], heap.getOrDefault(cs[j ++], 0) - 1);
            res = Math.max(res, i - j + 1);
        }

        return res;
    }
}
posted @ 2022-03-14 11:51  Lngstart  阅读(27)  评论(0编辑  收藏  举报