题目:无重复字符的最长子串

用到的是滑动窗口和unorder_map,

通过两个条件限制窗口范围:

1.当(left,right)存在重复字符时,那么(left,right+1…..right+n)都存在重复数值

2.当(left,right)不存在重复字符时,那么(left+1….left+n,right)都不存在重复字符

因此,(left,right+1…..right+n)与(left+1….left+n,right)都不需要再去进行遍历

核心:用unordered_map记录每个字符的出现次数

 1
 2int lengthOfLongestSubstring(string s)
 3
 4{
 5
 6    int maxStr = 0; // 用来记录出现过的“最长”无重复子串的长度。
 7
 8
 9
10    // 这里的 um (unordered_map) 是核心工具。
11
12    // Key (char): 窗口里的字符
13
14    // Value (int): 这个字符在当前窗口里出现了几次
15
16    std::unordered_map<char, int> um;
17
18
19
20    // 开始滑动窗口。一开始,左右边界都在最左边(索引 0)。
21
22    // right++ 代表窗口的右边缘在不断向右扩展,吞进新的字符。
23
24    for(int left = 0, right = 0; right < s.size(); right++)
25
26    {
27
28        // s[right] 是刚刚进入窗口的新字符。
29
30        // um[s[right]]++ 的意思是:让这个新字符的出现次数 +1。
31
32        um[s[right]]++;
33
34
35
36        // 检查刚刚吞进来的字符,是不是导致窗口里有重复了?
37
38        // 如果 > 1,说明这个字符之前已经在窗口里存在了。
39
40        while(um[s[right]] > 1)
41
42        {
43
44            // 既然有重复了,就缩小窗口:
45
46            // 把最左边的字符 s[left] 踢出窗口,所以它的出现次数 -1。
47
48            um[s[left]]--;
49
50            // 左边界向右移动一格,窗口缩小。
51
52            left++;
53
54        }
55
56
57
58        // 此时认为窗口里已经没有重复字符了。
59
60        // right - left + 1 就是当前窗口的长度。
61
62        // 比如 left=0, right=2,长度就是 2 - 0 + 1 = 3。
63
64        // 用 std::max 更新历史最大长度。
65
66        maxStr = std::max(maxStr, right - left + 1);
67
68    }
69
70    return maxStr; // 遍历完整个字符串,返回找到的最大值。
71
72}