LeetCode OJ - Longest Substring Without Repeating Characters (-2*)

来源:互联网 发布:linux alias 编辑:程序博客网 时间:2024/05/27 00:46

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.

思路一:在i位置,求出i开头的子串的长度。通过逆序迭代求出在 0 位置得子串最大长度。时间复杂度太高O(n^2)

class Solution {public:    int lengthOfLongestSubstring(string s) {        int len = s.size();        if(len == 0) return 0;                int ret = 1;        for(int i = len - 1; i >= 0; i--) {            ret = max(ret, getlenSub(s, i));        }        return ret;    }        int getlenSub(string &s, int start) {        unordered_map<char, int> hash;        for(int i = start; i < s.size(); i++) {            if(hash[s[i]] <= 0) {                hash[s[i]] = 1;             }else{                break;            }        }        return hash.size();    }};


思路二:上面是逆向的过程,如果是正向的过程即为遍历每一个字母,迭代的处理以s[i]开头的子串。 

但是,这里发现在计算s[i+1]时,与s[i]相比有很多重复的工作。这样可以考虑,每次对s[i]处理时以s[i]开始向后处理,而不是向前,这样就有可能去重了对不对。



        那么可能会先考虑到第②种情况,当前s[i] = 'X',要让X往回走需要找到上一个X所在位置。但是又很担忧着两个X之间有重复元素则么办,如果我们在迭代过程中记录了不会重复的区域不就可以了。假设这里start + 1到i之间是没有重复元素的,那么ret = max(ret, i - start)。

        这里 (start , i) 表示了一片不会出现重复字母的区域。对于图①、③分别为ret = max(ret, i - start)和 ret = max(ret, i - history[‘X’])。

        当然了,start也可以表示从start开始后面没有重复元素。代码如下:

class Solution {public:    int lengthOfLongestSubstring(string s) {        int len = s.size();        if(len == 0) return 0;                int history[256];        memset(history, -1, sizeof(history));                int start = 0, ret = 0;        for(int i = 0; i < len; i++) {            if(start > history[s[i]] + 1) {                ret = max(ret, i - start + 1);                            } else {                ret = max(ret, i - history[s[i]]);                start = history[s[i]] + 1;            }            history[s[i]] = i;        }                return ret;                    }};

        这里还要维护start,分析上面的情况可以得出start = max(start, history['X'])。其中history值可以用hash表也可以用数组来维护。

class Solution {public:    int lengthOfLongestSubstring(string s) {        int len = s.size();        if(len == 0) return 0;                int history[256];        memset(history, -1, sizeof(history));                int start = -1, ret = 0;        for(int i = 0; i < len; i++) {            if(start > history[s[i]]) {             //history[x] < start                ret = max(ret, i - start);            } else {                                //start ≤ history[x]                ret = max(ret, i - history[s[i]]);                start = history[s[i]];            }            history[s[i]] = i;        }                return ret;               }};

        其中start的初始化需要注意,start位置表示其下一个位置开始不会有重复字符。而history初始化为 -1 ,数组开始之前假象history[‘X’]在-1位置更合理。

        如果想要记录最长的这些子串,并且统计,采用hash表记录即可

        

map<string, int> hash;int ret = 0;void lengthOfLongestSubstring(string s) {    int len = s.size();    if(len == 0) return;        int history[256];    memset(history, -1, sizeof(history));        int start = -1;//string single;    for(int i = 0; i < len; i++) {        if(start > history[s[i]]) {            ret = max(ret, i - start);//single = s.substr(start + 1, i - start);//hash[single]++;                    } else{            ret = max(ret, i - history[s[i]]);//single = s.substr(start + 1, i - history[s[i]]);//hash[single]++;            start = history[s[i]];        }        history[s[i]] = i;    }            }

0 0
原创粉丝点击