寻找最长无重复字符子串 Longest Substring Without Repeating Characters

来源:互联网 发布:java 数组定义方式 编辑:程序博客网 时间:2024/06/14 09:05

要求: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 substring is "b", with the length of 1.

思路:要统计出是否有重复出现的字符,一种最快最省空间的方法就是bitmap对26个字符进行统计。

注意一点就是,在字符串匹配过程中指针回溯问题:遇到重复字符后,左指针如果只前移1步然后继续下一轮判断,这样会产生不必要的比较。比较好的一个方案是当遇到重复字符后,将左指针移到重复字符的后面。如”abcdcabc“,遇到第二'c'时发现重复时,将左指针移到第一个‘c'后的位置。然后下一轮从那开始判断。从OJ结果来看,回溯较少的方案确实节省了运行时间。

代码一:

class Solution {public:    unsigned int status;    void add_to_set(char a)    {        int value = a - 'a';        unsigned int t=1;        status = status|(t<<value);    }        int exist_or_not(char a)    {        int value = a - 'a';        unsigned int t=1;        if( (status&(t<<value)) == 0)             return 0; //not exist        else            return 1; //do exist    }    int lengthOfLongestSubstring(string s) {        // Start typing your C/C++ solution below        // DO NOT write int main() function        int n = s.length();if(n==0)return 0;        if(n==1)            return 1;        int i,j;        int maxlen=-1;        i=0;while(i<n)        {status=0;            j = i;            while(j<n)            {                if(exist_or_not(s[j]) == 0)                {                    add_to_set(s[j]);                    if(j-i+1 > maxlen)                        maxlen = j-i+1;                    j++;                }                else                {while(s[i]!=s[j]){i++;}i++;break;                }            }if(j==n)break;        }return maxlen;    }};

代码二:在代码一中,如果遇到重复字符串,会通过遍历查找前一个重复字符的位置。实际上,如果用数组int[]来存储已出现的字符的下标位置,就不用再去查找了。这样就做到真正的线性时间复杂度O(N)。

class Solution {public:    int lengthOfLongestSubstring(string s) {        if(s.empty())            return 0;        int m[256]; //m[c-'a']记录某个字符c上次出现时的位置        memset(m, -1, sizeof(m));        int maxlen = 1;        int start = 0; //start记录当前非重复子串的左端位置        for(int i=0;i<s.size();i++)        {            if(m[s[i]] >= start) //字符s[i]在当前已经出现过            {                maxlen = max(maxlen, i - start);                start = m[s[i]] + 1; //更新当前非重复字符串            }            m[s[i]] = i;        }        maxlen = max(maxlen, (int)s.size() - start);        return maxlen;    }};
PS:leetcode测试用例库发生了变化,增加了小写字母以外的字符。

原创粉丝点击