Leetcode题目总结[3]无重复字符的最长字串
1.题目描述
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其
长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke"
,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
提示:
0 <= s.length <= 5 * 104
s
由英文字母、数字、符号和空格组成
2.做法
首先要分清楚子串和子序列
子串:串中任意个连续的字符组成的子序列称为该串的子串 如:coffee中的offe是一个子串
序列:序列是被排成一列的对象(或事件);这样每个元素不是在其他元素之前,就是在其他元素之后。这里,元素之间的顺序非常重要
子序列:子序列就是在原来序列中找出一部分组成的序列 如:coffee中的ofe可以是一个子序列,而不可以是一个子串
一开始啥想法都没有,瞄了一眼题解,滑动窗口+hashmap?
看了一会迷迷糊糊地也没怎么看懂 但是到自己真动手写的时候就知道为什么是滑动窗口+hashmap了
最暴力的做法就是枚举出所有区间并判断区间内是否有重复字符 并找出符合条件的最长区间
一共有Σ? 好吧算不出来总之就是很多个不合法区间
我们可以利用两个指针组成一个滑动窗口,从左往右移动窗口,每次右指针右移一位,加入一个字符,并判断现在的字串里有没有与新字符相同的字符,如果有,则加入这个新字符以后的子串不合法。
我们可以记录一下没加入新字符时的字串长度,
然后将左指针右移继续计算下面的字串
当所有的可能的合法区间都枚举并计算一遍后即可得到答案
判断:这里我是直接循环区间挨个字符判断,不知道有没有其他做法 比如利用hash表中存的字符出现的最后位置与指针位置比较直接判断之类的?(临时想法也没有试过也许有点得不偿失?)
左指针右移:一开始我以为只是单纯右移一位就可以了(只考虑了样例1的情况),但是右移之后遇到同样的字符会出问题(卡了样例3) 记录完pw子串的长度后 这个p就没有用了 因为以这个p开头的子串最长只能到这里,所以我们可以在记录完子串长度后就将这个p废弃掉, pw中的w也是,假如你说两个重复w直接可能还有其它合法字符,但是在遇到第二个w之后,以第一个w开头的子串最长也就到第二个子串为止,而以第一个w后面的字符开头的子串可能还会更长,所以我们可以舍弃掉第一个w,可以直接将左指针跳到第一个w+1的位置。于是我们用hash记录每个字符对应的最后出现的位置,在左指针右移时直接移动到对应位置+1就可以了。c++我用的不熟,就用数组暂时代替了
3.代码
C++:
1 /* 2 * @lc app=leetcode.cn id=3 lang=cpp 3 * 4 * [3] 无重复字符的最长子串 5 */ 6 7 // @lc code=start 8 class Solution { 9 public: 10 int lengthOfLongestSubstring(string s) { 11 int len = s.length(); 12 int maxans = 0; 13 int start = 0,flag = 0; 14 int temp; 15 int a[500]= {}; 16 if(len == 0) return 0; 17 for(int i = 0; i < len; i++) 18 { 19 20 for(int j = start; j < i; j++) 21 { 22 if(s[j] == s[i]) 23 { 24 flag = 1; 25 temp = a[s[i] - ' '] + 1; 26 break; 27 } 28 } 29 if(flag == 1) 30 { 31 start = temp; 32 } 33 maxans = max(maxans,i - start + 1); 34 flag = 0; 35 a[s[i] - ' '] = i; 36 } 37 return maxans; 38 } 39 }; 40 // @lc code=end
4.做题时遇到的错误
runtime error: index -65 out of bounds for type ‘int [26]’
错误原因是数组越界
因为题目没有限制字符一定是26个英文字母,也可能有'-' ' ' '?' '!' '*'等符号
在建立hash表的时候要将表的范围扩大一点
我将表的范围扩到了500就可以了 (随便选的数字)