[LeetCode] 3. Longest Substring Without Repeating Characters 最长无重复字符的子串

1.暴力法:

本题让求给定字符串的最长的无重复字符的子串,首先想到暴力解法,穷举出字符串的所有子串,并判断每个子串是否是不重复子串,具体使用hashset或set判是否有重复字符;暴力法效率很差,时间O(n^3),空间O(n);参考代码如下:

 1 class Solution {
 2 public:
 3     int lengthOfLongestSubstring(string s){
 4         int res = 0;
 5         const int size = s.size();
 6         if(s.empty()) return 0;
 7         if(size<=1) return size;
 8         for(int i = 0;i<size;++i)
 9            for(int j = i;j<size;++j)
10            {
11                 int sub_seq = j-i+1;
12                 if(isNoreapeatSubstring(i,j,s)){
13                     if(sub_seq>=res)
14                        res = sub_seq;
15                 }
16            }
17         return res;
18     }
19
20     bool isNoreapeatSubstring(int l,int h,string &s)
21     {
22         set<char> charSet;
23         for(int i =l;i<=h;i++)
24         {
25             if(charSet.find(s[i])==charSet.end())
26              {
27                  charSet.insert(s[i]);
28              }
29              else{
30                  return false;
31              }
32         }
33         return true;
34     }
35 };

2.动态规划 

稍加思考,很容易发现本题是一个具有最优子结构的最优解问题,所以可以用动态规划的方法;

2.1 定义状态

dp[i]: 字符串s中,以字符s[i]结尾的最长的不重复子串的长度;

2.2  转态转移 (方程)

当s[i]和以s[i-1]结尾的最长不重复子串中所有的字符都不相同时,dp[i] =  dp[i-1]+1;否则,找以s[i-1]结尾的最长不重复子串中和s[i]重复的最后的字符位置index,则

dp[i]=i-1-index+1; 动态规划的时间O(n^2),空间O(n^2);

参考代码如下:

 1 class Solution {
 2 public:
 3     int lengthOfLongestSubstring(string s) {
 4         const int size = s.size();
 5         if(s.empty()) return 0;
 6         if(size<=1) return size;
 7         int dp[size];//dp[i]表示以s[i]结尾的不重复子串
 8         memset(dp,0,size);
 9         int res = 1;
10         dp[0]=1;//dp初始值
11         for(int i = 1;i<size;++i)
12         {
13             bool reapeat = false;
14             int index = 0;
15             for(int j = i-1;j>= i-1-dp[i-1]+1;j--)
16             {
17                  if(s[j]==s[i])
18                  {
19                      reapeat = true;
20                      index = j ;//最近的一次重复
21                      break;
22                  }
23             }
24             if(reapeat)//重复
25             {
26                 dp[i]=i-1-index+1;
27             }
28             else //不重复
29             {
30                 dp[i]=dp[i-1]+1;
31             }
32             if(dp[i]>=res)
33                 res=dp[i];
34         }
35         return res;
36     }
37 };

3.滑动窗口+hash表 法

可以在遍历字符串 的过程中维护一个滑动窗口,使得滑动窗口内的子串表示字符串的当前最长不重复子串,具体地,使用hashmap  m记录字符串中字符和其最后一次出现的位置之间的映射;定义变量left,res,left表示滑动窗口的左边界的前一个位置,初始化为-1,res表示滑动窗口的长度最大值;

遍历到一个字符s[i]时,如果字符在hashmap中,且最后一次的位置在滑动窗口内(i>left),将滑动窗口的边界右移,left = m[s[i]];然后更新hash表,

使用滑动窗口+hash表的方法可以实现最好的效率,因为只需遍历一遍,所以时间O(n),因为字符的个数是一定的(最多128个)所有空间O(1),

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
       int res = 0,left = -1,str_len=s.size();//
       unordered_map<int,int> m;//映射字符中字符和其最后一次出现的位置
       for(int i = 0;i< str_len;++i)
       {
           if(m.count(s[i])&&m[s[i]]>left){
               left = m[s[i]];
           }
            m[s[i]] = i;//更新字符最后一次出现的位置
            res = max(res,i-left);
       }
       return res;
    }
};

下面这种写法是上面解法的精简模式,这里我们可以建立一个 256 位大小的整型数组来代替 HashMap,这样做的原因是 ASCII 表共能表示 256 个字符,但是由于键盘只能表示 128 个字符,所以用 128 也行,然后全部初始化为 -1,这样的好处是不用像之前的 HashMap 一样要查找当前字符是否存在映射对了,对于每一个遍历到的字符,直接用其在数组中的值来更新 left,因为默认是 -1,而 left 初始化也是 -1,所以并不会产生错误,这样就省了 if 判断的步骤,其余思路都一样:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        vector<int> m(128, -1);
        int res = 0, left = -1;
        for (int i = 0; i < s.size(); ++i) {
            left = max(left, m[s[i]]);
            m[s[i]] = i;
            res = max(res, i - left);
        }
        return res;
    }
};

原文地址:https://www.cnblogs.com/wangxf2019/p/12160641.html

时间: 2024-10-11 22:59:09

[LeetCode] 3. Longest Substring Without Repeating Characters 最长无重复字符的子串的相关文章

lintcode 中等题:longest substring without repeating characters 最长无重复字符的子串

题目 最长无重复字符的子串给定一个字符串,请找出其中无重复字符的最长子字符串. 例如,在"abcabcbb"中,其无重复字符的最长子字符串是"abc",其长度为 3. 对于,"bbbbb",其无重复字符的最长子字符串为"b",长度为1. 解题 利用HashMap,map中不存在就一直加入,存在的时候,找到相同字符的位置,情况map,更改下标 public class Solution { /** * @param s: a s

[LeetCode] Longest Substring Without Repeating Characters 最长无重复字符的子串 C++语言 java语言实现

Given a string, find the length of the longest substring without repeating characters. Example 1: Input: "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3. Example 2: Input: "bbbbb" Output: 1 Explana

Leetcode 3 Longest Substring Without Repeating Characters. (最长无重复字符子串) (滑动窗口, 双指针)

目录 问题描述 例子 方法 Leetcode 3 问题描述 Given a string, find the length of the longest substring without repeating characters. 例子 Example 1: Input: "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3. Example 2: Input: &q

[LeetCode] Longest substring without repeating characters 最长无重复子串

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest subst

[LeetCode] Longest Substring Without Repeating Characters最长无重复子串

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest subst

【LeetCode每天一题】Longest Substring Without Repeating Characters(最长无重复的字串)

Given a string, find the length of the longest substring without repeating characters. Example 1:           Input: "abcabcbb"                              Output: 3                           Explanation: The answer is "abc", with the l

【Leetcode】【Longest Substring Without Repeating Characters】【无重复字符的最长子串】【C++】

题目:给定一字符串,求其无重复字符的最长子串长度. 思路:for循环一次,时间复杂度为O(N).字符的ascii值为32~126.start表示当前无重复字符子串的初始位置,初始值为0:可定义一个位置数组pos[128]表示for循环索引到当前位置时相应的字符对应的位置.若当前字符s[i](其ascii值为cur_pos),若pos[cur_pos]>=start,说明在start之后已有该字符s[i],则以start开始的子串第一次遇到重复字符,打住.判断当前长度是否大于max_len,若大于

[LeetCode] 5. Longest Substring Without Repeating Characters 最长回文子串

[LeetCode] 5. Longest Substring Without Repeating Characters Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Example 1: Input: "babad" Output: "bab" Note: "aba&qu

LeetCode Longest Substring Without Repeating Characters 最长不重复子串

题意:给一字符串,求一个子串的长度,该子串满足所有字符都不重复.字符可能包含标点之类的,不仅仅是字母.按ASCII码算,就有2^8=128个. 思路:从左到右扫每个字符,判断该字符距离上一次出现的距离是多少,若大于max,则更新max.若小于,则不更新.每扫到一个字符就需要更新他的出现位置了.这里边还有个注意点,举例说明: 假如有长为16串 s="arbtbqwecpoiuyca" 当扫到第2个b时,距离上一个b的距离是2:(直接减) 当扫到第2个c时,距离上一个c的距离是6:(直接减