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

2021-08-09  本文已影响0人  gykimo

题目:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

我的方法一:动态规划,O(N*N),O(N)

步骤

  1. 子问题
    1.1 最后一步:最长子串或者包含最后一个字符,或者不包含
    1.2 子问题:去除最后一个字符的字符串的最长子串的长度,和以最后一个字符为结尾的最长子串的长度谁大
  2. 转移方程
    dp[n] = max(dp[n-1], 以最后一个字符为结尾的不重复字符的长度)
  3. 初始条件
    dp[0] = 1;
  4. 边界条件
    n<s.size()
  5. 计算顺序
    dp[0] dp[1] dp[N]
  6. 优化点,有dp[n]只和dp[n-1]有关,所以没必要保存所有的dp,只记录当前已知最大的即可。

复杂度

时间:两层循环,所以最大是O(N*N)
空间:使用了哈希表,当所有字符都不相同时,最大是O(N)

代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size() == 0){
            return 0;
        }

        unordered_set<char> set;
        const char* p_s = s.c_str();
        int size = s.size();
        int max_long = 0;
        char tmp;

        //时间O(N),空间set最大是O(N)
        for(int i = 0; i < size; i++){
            set.clear();

            //时间最大是O(N)
            for(int j = i; j >= 0; j--){
                tmp = p_s[j];
                if(set.find(tmp) != set.end()){
                    break;
                }
                set.insert(tmp);
            }

            if(max_long < set.size()){
                max_long = set.size();
            }
        }

        return max_long;
    }
};

我的方法二:双指针,O(N),最大O(N)

和官方解法的滑动窗口类似,

步骤

  1. 快慢指针,都从第0个字符开始遍历;使用一个哈希表set存储当前以快指针为结尾的不重复字符串;
  2. 先判断快指针对应的字符是否在set中,如果不在,说明该字符可以加到set中,这样长度就会变长;如果字符在set中,说明存在重复的字符,这个时候移动慢指针,并将慢指针对应的字符从set中去除,直到将快指针对应的字符从set移除为止;
  3. 期间set的最大长度就是最终的结果

初始条件

  1. 快慢指针都指向第一个字符

边界条件

  1. 快指针遍历完了整个字符串

复杂度

时间:O(N),快指针遍历了一遍,慢指针最大遍历了一遍,所以整体是O(N)
空间:最大O(N),当所有字符都不想等时,set的长度就是字符串的长度,所以是O(N)。

代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size() == 0){
            return 0;
        }

        unordered_set<char> set;
        const char* p_s = s.c_str();
        int size = s.size();
        int max_long = 0;
        char tmp;

        int left = 0;
        int right = 0;

        //时间复杂度是O(N),因为right和left最大都从0遍历到N
        //空间复杂度最大是O(N)
        while(right < size) {
            if(set.find(p_s[right]) == set.end()){
                set.insert(p_s[right]);
                right++;

                if(set.size() > max_long){
                    max_long = set.size();
                }
            }else{
                set.erase(p_s[left]);
                left++;
            }
        }

        return max_long;
    }
};
上一篇下一篇

猜你喜欢

热点阅读