无重复字符的最长字串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
滑动窗口:维护一个左指针和一个右指针,维护窗口两端的索引,且 right 每次向右走一个索引。建一个无序集合来存储现在窗口中的字符,出现重复就将窗口左索引向右移动,直到 right 加入的新字符无重复为止,随后加入 s[right]。每次完成新元素加入时更新最大窗口长度,得到最大窗口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Solution { public: int lengthOfLongestSubstring(string s) { unordered_set<char> window; int left = 0, maxLen = 0; int str_size = s.size(); for (int right = 0; right < str_size; ++right) { while (window.count(s[right])) { window.erase(s[left]); ++left; } window.insert(s[right]); maxLen = max(maxLen, right - left + 1); } return maxLen; } };
|
这个方法似乎效率有些低?反复对 unordered 做加入和擦除操作会拖慢运行速度。用一个长度为 128(或 256,覆盖 ASCII)的 int 数组 lastPos,初始值为 -1,记录每个字符最近一次出现的索引。 右指针 right 遍历时:
- 如果
lastPos[s[right]] >= left,说明当前字符在窗口内重复,直接将 left 跳到 lastPos[s[right]] + 1,无需循环。
- 更新
lastPos[s[right]] = right,计算当前窗口长度。
这样完全去掉了哈希集合和内层 while 循环,每个字符只有一次数组读写,常数极小。
被刚会用的哈希坑了啊。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public: int lengthOfLongestSubstring(string s) { vector<int> lastPos(128, -1); int left = 0, maxLen = 0; for (int right = 0; right < s.size(); ++right) { char c = s[right]; if (lastPos[c] >= left) { left = lastPos[c] + 1; } lastPos[c] = right; maxLen = max(maxLen, right - left + 1); } return maxLen; } };
|
找到字符串中所有字母异位词
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
也是滑动窗口,但是是固定宽度的。
用两个长度为 26 的数组 pCount 和 windowCount 记录字符出现次数。初始时统计 p 的频率,以及 s 前 p.size() 个字符的频率。若两数组相等,记录起始索引 0。窗口每次右移一位,加入右边新字符,移除左边旧字符,更新频率后比较。相等则记录左边界索引。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Solution { public: vector<int> findAnagrams(string s, string p) { vector<int> result; int sLen = s.size(), pLen = p.size(); if (sLen < pLen) return result;
vector<int> pCount(26, 0), windowCount(26, 0); for (int i = 0; i < pLen; ++i) { pCount[p[i] - 'a']++; windowCount[s[i] - 'a']++; } if (pCount == windowCount) result.push_back(0);
for (int i = pLen; i < sLen; ++i) { windowCount[s[i] - 'a']++; windowCount[s[i - pLen] - 'a']--; if (pCount == windowCount) { result.push_back(i - pLen + 1); } } return result; } };
|