力扣题库第三题
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
题外话:
此题给出的难度是中等,确实也比较容易确定思路,此次敲完代码调试完毕后提交,发现解是解出来了,效率击败9%的人,占内存击败11%的人。。。让我觉得自己是个five😌
不过后来反应过来,因为大家学习高亮解后自我优化,尝试的多了,提交的多了,整体效率和内存占用自然都上去了,所以实属正常。各位朋友如果有相似的疑惑,不用多想,放开抡自我提升就好了。
解题:
这次题目有点似曾相识,记得以前考研时复习数据结构就遇到过类似的题,是有固定解法的,但是比较久远了就没管,恰好前两天复习了HashMap就用这个顺了顺思路开始解题了。看了评论区,发现用set解效率更高,就也用set试了一下。
最后去仔细推敲了下评论区的最高亮解,确实特别巧妙,有两点,一个点是将字符串化为一个数组,按照ASCII码为index查看字符的位置,化为索引查找;另一个点是,这让我想起了遥远的数据结构的答案,思路和该解不谋而合。下面代码看起来。
一、首先想到的解法,利用HashMap,实际也是双重循环
class Solution {
public int lengthOfLongestSubstring(String s) {
//利用hashmap
char [] array = s.toCharArray();
//记录最大长度
int result = 0;
//记录起点
int flag = 0;
HashMap <String,Integer> map = new HashMap<String,Integer> ();
for(int i=0;i<array.length;i++){
if(!map.containsKey(String.valueOf(array[i]))){
map.put(String.valueOf(array[i]),i);
if(map.size()>result){
result = map.size();
}
}else{
if(map.size()>result){
result = map.size();
}
map.clear();
flag++;
i = flag;
map.put(String.valueOf(array[flag]),flag);
}
}
return result;
}
}
二、将HashMap换为set
class Solution {
public int lengthOfLongestSubstring(String s) {
//集合 思路和之前差别不算大 效率高点
Set<Character> set=new HashSet<>();
char [] arr=s.toCharArray();
int result = 0;
for (int i = 0, j = 0; j < arr.length; j ++ )
{
char comp=arr[j];
//remove from window
while (set.contains(comp))
set.remove(arr[i++]);
//add to right;
set.add(comp);
//compare with the result
result = Math.max(result, j - i + 1);
}
return result;
}
}
三、将字符串化为一个数组,按照ASCII码为index查看字符的位置,化为索引查找。遇到重复的字符就更改一次起始位置(可能会变大,也可能会变小),而最大串长度一直取“已知最大串”和“目前连续字符串(遍历位置-起始位置)”两者中的最大值。如此一来,这就彻底只需要遍历一次了。
class Solution {
public int lengthOfLongestSubstring(String s) {
//将字符串化为一个数组,按照ASCII码为index查看字符的位置,化为索引查找。
//记录字符上一次出现的位置
int [] last = new int [128];
int n = s.length();
int result = 0;
int start = 0;
for(int i = 0; i < n; i++){
//字符串第i位字符的ASCII码
int index = s.charAt(i);
//start可能会变大也可能会变小
start = Math.max(start, last[index]);
//若等到下一个相同的字符出现,result将做出改变;若无下一个相同字符,就等到遍历结束。
result = Math.max(result, i - start +1);
last [index] = i + 1;
}
return result;
}
}