leetcode/algorithm 3. Longest Substring Without Repeating Characters

问题:

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,主要为了短,省去好多中间变量,因此也得多求好几次值,使得耗时增加。。 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值