今天突然发现leetcode有中文版了,名字叫领扣,牛逼牛逼,中文版最大的好处在于题目理解更快,并且页面载入的速度会快很多,并且中文版和英文版的数据库还没有合并,楼主相当于重新刷一遍,因此之后的都以中文为主,废话少说,上题目与解答

给定一个字符串,找出不含有重复字符的最长子串的长度。

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 无重复字符的最长子串是 "abc",其长度为 3。
示例 2:

输入: "bbbbb"
输出: 1
解释: 无重复字符的最长子串是 "b",其长度为 1。
示例 3:

输入: "pwwkew"
输出: 3
解释: 无重复字符的最长子串是 "wke",其长度为 3。
     请注意,答案必须是一个子串,"pwke" 是一个子序列 而不是子串。

这道题目题意说的很清楚了,很粗暴的想法使用变化大小的滑窗去做,遍历滑窗的大小,对于某个大小的滑窗,使用hashmap或者set看是否存在重复的元素,这样的复杂度是O(n^2)。
显然这种做法不是我们想要的,这道题和楼主前几天一个面试中的问题类似,题目是找寻一个数组中,最大的连续子数组,要求子数组的和大于某个数。输入是数组与大于的数,输出是数组,那道题目的解法是两个指针,这里也类似,使用两个指针

方法:

  1. 设立两个指针l与r,或者不叫指针叫index
  2. 维护一个unordered_map<char, int>中包含[l,r]之间的元素出现的次数
  3. 一旦l等于r或者r指向的元素次数为0,unordered_map中的计数增加,并且r右移
  4. 一旦r指向的元素次数不为0,unordered_map相应元素计数减少,l右移

O(n)复杂度即可

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> m;
        for(int i = 0; i < s.size(); ++i){
            m[s[i]] = 0;
        }
        int l = 0, r = 0, res = 0;
        while(r < s.size() && l < s.size()){
            if(l == r || m[s[r]] == 0){
                m[s[r]]++;
                ++r;
            }else if(m[s[r]] >= 0){
                m[s[l]]--;
                ++l;
            }
            res = max(res, r - l);
        }
        return res;
    }
};

欢迎小伙伴投票?,欢迎留言讨论


juji
0 声望0 粉丝

相信技术改变人类,做芯片才能救中国