无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
class Solution { public: int lengthOfLongestSubstring(string s) { int maxlen = 0; int curlen = 0; unordered_map<char,int> charMap; for(int i = 0; i < s.size(); i++){ if(charMap.find(s[i]) == charMap.end()){ charMap[s[i]] = i+1; curlen += 1; } else{ curlen = min(i+1 - charMap[s[i]], curlen+1); charMap[s[i]] = i+1; } maxlen = maxlen < curlen ? curlen : maxlen; } return maxlen; } };
解题思路:
我是这么思考的:以 s[i] 结尾的子串跟以 s[i-1] 结尾的子串有什么关系?
假设我们已知以 s[i-1] 结尾的无重复字符最长子串的长度,那么对于以 s[i] 结尾的子串来说,无非就是两种可能:
1. s[i] 曾出现过
2. s[i] 未曾出现过
情况1简单啊,那就在前者长度的基础上+1呗
情况2我们要稍微讨论一下:
(1)如果 s[j] = s[k] = s[i],j < k < i,也就是说前面的子串出现过两次 s[i] 了,那么计算以 s[i] 为结尾的最长无重复字符子串长度时,我们肯定是拿 s[i] 跟s[k] 来计算,而不会拿 s[j]。这意味着我们可以用一个hashmap存储字符的位置,并且在每次出现重复字符的时候,更新hashmap。
(2)如果前面出现过 s[i],那我们计算长度的时候是不是直接 i - k 就好了呢?当然不是,因为 k 到 i 之间的这个子串可能还有其他字符的重复字符,比如: “abba”。
假设我们用 lastlen 和 curlen 分别记录以 s[i-1],s[i] 结尾的最长无重复字符子串的长度
那么 curlen = min(lastlen+1, i - k)
因为如果 k 到 i 之间的子串出现重复字符了,那么 i - k 肯定大于 lastlen + 1,此时我们要用 lastlen 来计算 curlen,而不能拿 i 和 k来计算
如果k 到 i 之间的子串没有出现重复字符,那么 i - k 会等于 lastlen + 1,所以取最小值是ok的。