【LeetCode-字符串】无重复字符的最长子串

题目描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例:

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

题目链接: https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

思路1

使用类似于求最大自序和的方法。设置两个指针left和right,left初始化为0,right初始化为1:

  • 判断当前字符s[right]是否在字符串s的[left,right)范围内出现过:
    • 如果没有出现,则将无重复子串长度加一,更新目前的无重复最长子串长度, right++;
    • 如果出现了,则将left更新为[left,right)范围内与当前字符s[right]相同且离得最远的字符下标,然后加1,求目前的子串长度,然后更新目前的无重复最长子串长度;
  • 重复上面的过程,直至rihgt>=s.length().
    代码如下:
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.empty() || s.length()==1){
            return s.length();
        }

        int left = 0;
        int right = left+1;
        int maxSubStrLen = 1;
        int curLen = 1;
        while(right<s.length()){
            int idx = find(s, left, right, s[right]);
            if(idx==-1){    // s[right]在[left,right)范围内没有出现
                curLen++;
                right++;
                maxSubStrLen = max(curLen, maxSubStrLen);
            }else{ // s[right]在[left,right)范围内出现
                left = idx+1;   // left此时是[left,right)范围内与s[right]相等且距离最远的下标+1
                right++;
                curLen = right-left;
                maxSubStrLen = max(curLen, maxSubStrLen);
            }
        }
        return maxSubStrLen;
    }
    /*查找c是否在字符串s的[left,right)范围出现,如果出现则返回下标,否则返回-1*/
    int find(string s, int left, int right, char c){
        for(int i=left; i<right; i++){
            if(c==s[i]){
                return i;
            }
        }
        return -1;
    }
};
  • 时间复杂度: O(n^2)
    首先遍历一遍元素,在遍历每个元素的过程中还要查看该元素是否在前面出现过。
  • 空间复杂度:O(1)

思路2

维持一个队列,该队列中不包含重复的元素,且该队列中的元素是连续的(滑动窗口)。例如字符串"abcabcbb",假设当前队列中的元素为前3个字符"abc",下一个元素为"a",在队列中出现过,则将队列最左边的元素移除,直至队列中不包含下一个元素"a",记录当前的长度和当前的最大长度。代码如下:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.empty() || s.length()==1){
            return s.length();
        }

        unordered_set<char> lookup;
        int left = 0;
        int right = 0;
        int maxSubStrLen =1;
        while(right<s.length()){
            if(lookup.find(s[right])!=lookup.end()){    // 当前元素s[right]在窗口中出现
                lookup.erase(s[left]);
                left++;
            }else{  // 当前元素s[right]没有在窗口中出现
                int curLen = right-left+1;
                maxSubStrLen = max(curLen, maxSubStrLen);
                lookup.insert(s[right]);
                right++;
            }
        }
        return maxSubStrLen;
    }
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)
    虽然使用了set,但由于字符个数有限(256个),所以辅助空间的规模不会随输入规模的增大而增大,所以空间复杂度为O(1)。

参考

1、https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/hua-dong-chuang-kou-by-powcai/

原文地址:https://www.cnblogs.com/flix/p/12679874.html