leetcode/algorithm 3. Longest Substring Without Repeating Characters

来源:互联网 发布:美国经济数据gdp 编辑:程序博客网 时间:2024/05/01 07:49
问题:

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given "bbbbb", the answer is "b", with the length of 1.

Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring"pwke" is a subsequence and not a substring.

Subscribe to see which companies asked this question.

最开始直接用从0移动到string尾部,通过定义一个含有256个int数组来统计char的出现与否,好像类似hash,刚开始以为也要返回string,且对拷贝也没多严格限制,得到

class Solution {public:    int lengthOfLongestSubstring(string s) {        string output = "", s_out = "";        int map[256] = {0};        int length = 0, size = s.size(), temp = 0, len_out = 0;        while (temp < size) {            if (!map[s[temp]]) {                ++map[s[temp]];                ++length;                output += s[temp];            } else {                if (length > len_out) {                    len_out = length;                    s_out = output;                }                auto a = output.find(s[temp]);                for (int i = 0; i < a; ++i)                    map[output[i]] = 0;                output = output.substr(a + 1) + s[temp];                length -= a;            }            ++temp;        }        if (length > len_out) {            len_out = length;            s_out = output;        }        return len_out;    }};
32ms ac

后面对代码优化,主要减少了不必要的复制操作,并且hash的数组不单单可以记录char是否出现,还能记录出现的位置,这样省去更多条件判断,得到

class Solution {public:    int lengthOfLongestSubstring(string s) {        auto size = s.size();        string::size_type i = 0, j = 0, len_out = 0, length = 0;        decltype(size) map[256] = {0};        while (i<size && j<size) {            if ( (!map[s[j]]) && ((s[i] != s[j]) || (i == j)) ) {                map[s[j]] = j;                ++j;                ++length;            }            else {                if (length > len_out)                    len_out = length;                for (auto k = i; k < map[s[j]]; ++k)                    map[s[k]] = 0;                i = map[s[j]] + 1;                map[s[j]] = j;                length = j - i + 1;                ++j;            }        }        if (length > len_out)            len_out = length;        return len_out;    }};

19ms ac,这里主要一直在纠结
 if ( (!map[s[j]]) && ((s[i] != s[j]) || (i == j)) )  
这里条件一直写错。。

后面看了题解,发现可以更简单的判断,第二个答案还是需要清零hash数组,假设子串由前后位置分别由下标i,j标记,则我们可以通过判断当前char的hash值是否超过i,如果超过i,则有重复,如果没有,则没重复,这样的话,就不用对hash数组进行清零操作了。。

class Solution {public:    int lengthOfLongestSubstring(string s) {        auto size = s.size();        int i = 0, j = 0, len_out = 0, length = 0;        vector<int> map(256, -1);        while (j<size) {            if ( map[s[j]] < i) {                map[s[j]] = j;                ++j;                ++length;            }            else {                if (length > len_out)                    len_out = length;                i = map[s[j]] + 1;                map[s[j]] = j;                length = j - i + 1;                ++j;            }        }        if (length > len_out)            len_out = length;        return len_out;    }};
12ms ac 果然更快了。。


最后看到一个9行的答案,整理了一下while里面的条件判断的重复步骤,学着写了一下

class Solution {public:    int lengthOfLongestSubstring(string s) {        auto size = s.size();        int i = 0, j = 0, len_out = 0;        vector<int> map(256, -1);        while (j<size) {            if ( map[s[j]] >= i)                i = map[s[j]] + 1;            map[s[j]] = j;            len_out = len_out > j - i + 1 ? len_out : j - i + 1;            ++j;        }        return len_out;    }};

25ms ac,主要为了短,省去好多中间变量,因此也得多求好几次值,使得耗时增加。。 



0 0