LeetCode 3. Longest Substring Without Repeating Characters

问题链接

LeetCode 3

题目解析

求字符串的最长无重复子串

解题思路

第一个问题是子串,注意是连续的。

建立一个符号哈希数组 \(in[256]\),代表该符号时候出现过,256大小是因为ASCII表共能表示256个字符。初始化为0,代表未出现,当 \(in[i] > 0\) 时,表示该字符最近出现的索引位置+1。

定义变量\(res\):记录最长无重复子串长度;\(left\)包含当前字符的最长无重复子串的起始位置。遍历字符串,遇到未出现的字符(\(in[s[i]] == 0\))时,更新 \(res\);注意另一种情况,当哈希表中的值小于 \(left\),原因是出现过重复的字符,导致 \(left\) 的位置更新了(变大),如果又遇到了新的字符或者虽然重复,但重复位置在 \(left\) 之前,也需要更新 \(res\)。否则的话,就要更新 \(left\) 的位置为 \(in[s[i]]\)

\(left\) 更新问题:注意理解更新 \(left\) 的条件,一方面理解:无法更新 \(res\),就要更新 \(left\),二者是对立的;另一方面,直接理解更新条件:\(in[s[i]] > 0 && in[s[i]] >= left\)。在当前字符重复的情况下,且重复位置在 \(left\) 的右边时,更新 \(left\)

注意每次都需要更新 \(in[s[i]] = i+1\),目的是下次再遇到此字符时,直接将 \(left\) 赋值为 \(in[s[i]]\),保证无重复。

参考代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        vector<int> in(256, 0);
        int res = 0, left = 0;
        for (int i = 0; i < s.size(); i++) {
            if (in[s[i]] == 0 || in[s[i]] < left) {
                res = max(res, i-left+1);
            }
            else
                left = in[s[i]];
            in[s[i]] = i+1;
        }
        return res;
    }
};

思路一样,有一种更精简的写法。\(res\)\(left\) 的定义不变,\(in[s[i]]\) 的值稍微变化,变为字符最近出现的索引位置,没有+1。

先更新 \(left\),再更新 \(in[s[i]]\),最后更新 \(res\),妙不可言~

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        vector<int> in(256, -1);
        int res = 0, left = -1;
        for (int i = 0; i < s.size(); ++i) {
            left = max(left, in[s[i]]);
            in[s[i]] = i;
            res = max(res, i - left);
        }
        return res;
    }
};

解法二:set

运用集合(set),其特点是不包含重复元素。思路其实还是没有变,遍历字符串,把未出现过的字符都放入set中,更新结果res;如果遇到重复字符,则从左边开始删字符,直到删到集合中没有重复的字符停止。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        set<char> t;
        int res = 0, left = 0, right = 0;
        while (right < s.size()) {
            if (t.find(s[right]) == t.end()) {
                t.insert(s[right++]);
                res = max(res, (int)t.size());
            }  else {
                t.erase(s[left++]);
            }
        }
        return res;
    }
};

LeetCode All in One题解汇总(持续更新中...)

本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.


posted @ 2018-03-09 18:43  AlvinZH  阅读(362)  评论(0编辑  收藏  举报