重复字符的最长子串

给定1个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

解题思路:

创建一个数组,并初始化为0,数组一共有256个元素,数组下标代表字符的ASCII码。从头遍历字符串,当出现某个字符,就在该字符下标所在的数组元素记录该字符在字符串的偏移位置(相对起始位置)。遍历某个字符串字符发现该字符下标数组元素值为0,则代表该字符未出现过,并用left表示当前寻找最长子串的所在字符串起始位置(并不代表最长子串所在的字符串起始位置)。当遍历某个字符串字符发现该字符下标数组元素值为0时或小于left值时,无重复字符的长度为max(已经保存的最长长度值,当前遍历字符的偏移值-left+1).

 1 #include<string>
 2 #include<iostream>
 3 using namespace std;
 4 int lengthOfLongestSubstring(string s)
 5 {
 6     int m[256] = {0}, res = 0, left = 0;
 7     for (int i = 0; i < s.size(); ++i)
 8     {
 9         if (m[s[i]] == 0 || m[s[i]] < left)
10         {
11             res = max(res, i - left + 1);
12         } 
13         else
14         {
15             left = m[s[i]];
16         }
17             m[s[i]] = i + 1;
18     }
19      return res; 
20 }
21 int main()
22 {
23     string mystring;
24     while(1)
25     {
26         cin>>mystring;
27         if(mystring.compare("exit")==0)
28         {
29             break;
30         }
31         cout<<"最长无重复字符长度:"<<lengthOfLongestSubstring(mystring)<<endl;           
32     }
33     return 0;
34 }

程序中那个if条件语句中为啥要有个m[s[i]] < left,我们用一个例子来说明,当输入字符串为"abbca"的时候,当i=4时,也就是即将要开始遍历最后一个字母a时,此时数组中a字符下标所在的元素值对应1,b对应3,c对应4,left为2,即当前最长的子字符串的左边界为第二个b的位置,而第一个a已经不在当前最长的字符串的范围内了,那么对于i=4这个新进来的a,应该要加入结果中,而此时未被更新的哈希表中a为1,不是0,如果不判断它和left的关系的话,就无法更新结果,那么答案就会少一位,所以需要加m[s[i]] < left。

posted @ 2019-09-05 15:38  jest549  阅读(590)  评论(0编辑  收藏  举报