3. Longest Substring Without Repeating Characters
-
题目描述
-
题目思路:
这道题要求的是最长的子串而不是最长的子序列,在LeetCode上也给了提示
Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
先不考虑代码的问题,比如有一个字符串“abcabcbb”,要求找出其最长子串,可以一个一个字符的遍历,a,b,c,然后又出现了a,就把一开始已经遍历到的a去掉,变成b,c,a。然后遍历到b,就把已经遍历过的b去掉,变成c,a,b。重复这个过程,最终可以找到最长子串。
从上面的过程中可以看到,我们需要记录之前已经出现过的字符,可以统计字符出现的个数,但是这道题目,字符出现的顺序很重要,所以可以使用Hashmap来建立字符和位置之间的映射(一开始我也没有想到用Hashmap,是从网上查找资料才明白的)。之前我们手动找子串的过程实际是一个滑动窗口的过程,窗口内都是没有重复出现的字符,由于窗口在不断的向右滑动,因此只需要关心每一个字符最后出现的位置即可,并把这个位置和字符建立映射。
为了确定窗口的大小,就必须有一个left指针来指向窗口的前一个位置。然后i向右滑动,i - left就是当前窗口的大小(也是当前能找到的最长子串的长度)。
当窗口向右滑动,i++。遇到新的元素s[i],先判断该元素在Hashmap中有没有,如果没有,把当前的元素和他出现的位置插入到Hashmap中即可。如果Hashmap中已经有了该元素,那么就要更新left的值了,left应该更新为Hashmap中保存的s[i]的值。
- C++代码实现:
class Solution
{
public:
int lengthOfLongestSubstring(string s)
{
int left = -1; //滑动窗口的左边界
int res = 0; //最长无重复子串的长度
int n = s.size();
unordered_map<char, int> hmap;
for (int i = 0;i < n;i++)
{
if (hmap.count(s[i]) && hmap[s[i]] > left)
{
left = hmap[s[i]];
}
hmap[s[i]] = i;
res = max(res,i - left);
}
return res;
}
};
hmap.count(s[i])是查找s[i]在Hashmap中是否存在,他的返回值只有两种,若存在,则返回1,否则返回0。
- 参考资料:
1 《[LeetCode] 3. Longest Substring Without Repeating Characters 最长无重复字符的子串》 https://www.cnblogs.com/grandyang/p/4480780.html