[剑指offer]最长不含重复字符的子字符串

[剑指offer]最长不含重复字符的子字符串

剑指offer-最长不含重复字符的子字符串

题目描述

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

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

示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。

请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

提示:
s.length <= 40000

解题思路
  • 暴力解法,算上查找,时间复杂度为O(n3),空间复杂度O(1)
  • 动态规划
    • 状态定义:动态规划列表dp,dp[j]为字符s[j]结尾的最长不含重复字符的子字符串
    • 转移方程:固定右边界j,字符s[j]左边距离最近的相同字符为s[i],即s[j]=s[i]。当i<0,即s[j]左边没有相同字符,则dp[j]=dp[j-1]+1;当dp[j-1]=j-i,即s[i]在dp[j-1]子字符串之内,则dp[j]=j-i。当i<0时,dp[j-1]
    • dp[ j ] = dp[ j - 1 ] + 1(当dp[ j - 1 ] < j - i)
    • dp[ j ] = j - i(当dp[ j - 1] >= j - i)
  • 所以,问题是,遍历字符s[j]时,如何确定索引 i
    • 线性遍历
    • 哈希表
实现代码
//暴力解法
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len=s.length();
        if(len==0)
            return 0;
        int maxcount=1;
        int i=0;
        while(i
//动态规划-线性遍历1
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len=s.length();
        if(len==0)
            return 0;
        vector dp(len);
        dp[0]=1;
        for(int j=1;j=0){//确定i的位置
                if(s[i]==s[j])
                    break;
                i--;
            }
            if(dp[j-1]dp[i]?max:dp[i];
        }
        return max;
    }
};

时间复杂度为:O(n2)
空间复杂度为:O(n)
可以继续优化空间复杂度,因为返回值是dp列表的最大值,那么就可以用一个dp变量存储dp[j],变量max每次取最大值,就可以省去dp列表使用的O(n)的额外空间

//动态规划-线性遍历2
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len=s.length();
        if(len==0)
            return 0;
        int dp=1;
        int max=dp;
        for(int j=1;j=0){
                if(s[i]==s[j])
                    break;
                i--;
            }
            if(dpdp?max:dp;
        }        
        return max;
    }
};

时间复杂度:O(n2)
空间复杂度:O(1)
可以继续优化时间复杂度,使用哈希表存储各字符最后一次出现的位置,可以节省遍历查找s[i]的O(n)时间,而字符的 ASCII 码范围为 00 ~ 127127 ,哈希表最多使用 O(128) = O(1)大小的额外空间。

//动态规划-哈希表
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len=s.length();
        if(len==0)
            return 0;
        map mymap;
        for(int i=0;idp?max:dp;
            mymap[s[j]]=j;
        }        
        return max;
    }
};

时间复杂度:O(n)
空间复杂度:O(1)

你可能感兴趣的:(剑指offer)