首先,老原则,先直接上代码。
//
// Created by tannzh on 2020/6/11.
//
/*
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
*/
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
using namespace std;
class Solution {
public:
int lengthOfLongestSubstring(string s) {
size_t region = 0, start = 0;
unordered_map<char, size_t> trace;
for(size_t i = 0; i < s.size(); ++i){
auto found = trace.find(s[i]);
if(found != trace.end() && found->second >= start) {
region = std::max(region, i - start);
start = found->second + 1;
}
trace[s[i]] = i;
}
return std::max(region, s.size() - start);
}
};
int main(int argc, char **argv)
{
Solution s;
std::string testStr1 = "abcabcbb";
std::string testStr2 = "bbbbb";
std::string testStr3 = "pwwkew";
std::cout << testStr1 << ", lengthOfLongestSubstring: " << s.lengthOfLongestSubstring(testStr1) << std::endl;
std::cout << testStr2 << ", lengthOfLongestSubstring: " << s.lengthOfLongestSubstring(testStr2) << std::endl;
std::cout << testStr3 << ", lengthOfLongestSubstring: " << s.lengthOfLongestSubstring(testStr3) << std::endl;
return 0;
}
解题思路
首先,求的只是长度,那么一定有一个 trace 来边记录边比较(max)。
其次,没有重复字符几乎是唯一条件,那么检查重复显然用 k-v mapping.
最后,要考虑一次迭代过程中,如何度量这个长度。
设 substr 的起点为 start(s), 终点为 last(l). 每一次迭代,记录一张索引表。
上图所示,last 指向 `a`, 查询当前表可知,`a` 的位置记录在案,且 `pos >= start`. 故此刻诞生一个 substr. 长度为 `last - start`. s 更新位置为 `pos + 1`.
有:
auto found = cache.find(s[last]);
if (found != cache.end() && found->second >= start) {
region = max(region, last - start);
start = found->second + 1;
}
cache[s[last]] = last;
注意最终还需要比较一次,返回 max(ret, s.size() - start)