算法,不如说它是一种思考方式
算法专栏: 123
题目描述:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
来源:力扣(LeetCode)
难度:中等
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
最容易得到的一个方法:以字符串每一个字符作为开头,来测试可以有多长的无重复。
也就是双指针方法,左指针一直指向字符开头,右指针遍历字符,当有出现重复时,左指针移动,右指针再次遍历。
class Solution {
public static int lengthOfLongestSubstring(String s) {
int max_str=0;
if(s.length()==0||s.length()==1)return s.length();
Set<Character> strSet = new HashSet<Character>();
int n = s.length();
int rk = -1;
for (int i = 0; i < n; ++i) {
if (i != 0) {//去掉这个元素 移动左指针
strSet.remove(s.charAt(i - 1));
}
while (rk + 1 < n && !strSet.contains(s.charAt(rk + 1))) {//移动右指针
strSet.add(s.charAt(rk + 1));
++rk;
}
if(rk - i + 1>max_str)
max_str = rk - i + 1;
}
return max_str;
}
}
而这样其实做了许多重复工作。例如一个字符串:a b c b a d
,就知道从b
开始没必要了。为了这样,我们就像找到一个回溯的方法。于是可以用HashMap
来记录字符在字符串的索引来帮助回溯。
对于出现的重复字符,使用i=strMap.get(s.charAt(i));
来直接回溯,也就是前面的左指针移动,然后把HashMap
清空,代表右指针回归,重新遍历。
class Solution3{
public static int lengthOfLongestSubstring(String s) {
int max_str=0;
if(s.length()==0||s.length()==1)return s.length();
Map<Character,Integer> strMap=new HashMap<>();
int len=0;
for (int i = 0; i < s.length(); i++) {
if(!strMap.containsKey(s.charAt(i))){// 没有重复元素
strMap.put(s.charAt(i),i);
len++;
}
else{
if(len>max_str)max_str=len;
len=0;
i=strMap.get(s.charAt(i));
strMap.clear();
}
}
if(len>max_str)max_str=len;
return max_str;
}
}
发现清空HashMap
也是没必要的,而且造成浪费,于是思考一种更快捷的回退方法。
就是说在重复的元素前面的才需要去除,而且右指针不用回归,不用重复遍历。
class Solution3{
public static int lengthOfLongestSubstring(String s) {
int max_str=0;
if(s.length()==0||s.length()==1)return s.length();
Map<Character,Integer> strMap=new HashMap<>();
int len=0;
for (int i = 0; i < s.length(); i++) {
if(!strMap.containsKey(s.charAt(i))){// 没有重复元素
strMap.put(s.charAt(i),i);
len++;
}
else{
if(len>max_str)max_str=len;
int k=strMap.get(s.charAt(i));
len=i-k-1;
while(k>=0&&strMap.containsValue(k)){//只需要移除这些元素就可以了
strMap.remove(s.charAt(k));
k--;
}
i--;
}
}
if(len>max_str)max_str=len;
return max_str;
}
}
返回第一页。☝
☕物有本末,事有终始,知所先后。
☝☝☝☝☝我的CSDN☝☝☝☝☝☝