滑动窗口(用到Set和Map)
例题
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
题解
1.暴力解题法(简单)
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
int n = s.length();
int ans = 0;
for (int i = 0; i < n; i++) {
for(int j = i; j < n; j++) {
if(allUnique(s,i,j)) {
ans = Math.max(ans, j - i + 1);
}
}
}
System.out.println(ans);
scan.close();
}
private static boolean allUnique(String s, int start, int end) {
Set<Character> set = new HashSet<Character>();
for(int i = start; i <= end; i++) {
Character ch = s.charAt(i);
if(set.contains(ch)) {
return false;
}
set.add(ch);
}
return true;
}
}
时间复杂度太高,会超时。
注:Java Character 类 ->https://www.runoob.com/java/java-character.html
2.滑动窗口(HashSet)
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while(i < n && j < n) {
if(!set.contains(s.charAt(j))) {
set.add(s.charAt(j));
j++;
ans = Math.max(ans, j-i);
} else {
set.remove(s.charAt(i++));
}
}
System.out.println(ans);
scan.close();
}
}
3.优化后的滑动窗口(HashMap)
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
int n = s.length(), ans = 0;
Map<Character,Integer> map = new HashMap<>();
for(int j = 0, i = 0; j < n; j++) {
if(map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j))+1, i);
//abccad,i指向第二个c的时候,要判断是否包含a,这个时候发现已包含的a的位置是0,这个时候就需要指向两者的最大值了。
}
ans = Math.max(ans, j - i + 1);
map.put(s.charAt(j),j); //会更新重复元素的位置,其他元素还在里边
}
System.out.println(ans);
scan.close();
}
}
唉,这个i = Math.max(map.get(s.charAt(j))+1, i);
语句真的是难住我了好一会,好久没想过来,不过还好一个评论点通了我。
前两种解法用HashSet来判断是否已经存在该字符
最后一种用HashMap来判断是否已存在该字符,并且可以知道该字符的位置。
注:这几个算法的代码和leedcode官方答案会有一丢丢的不同,有的设置是按照我自己习惯来的(比如i,j是否+1),不过算法思想是相同的。
转载:https://blog.csdn.net/weixin_40736438/article/details/102575659
查看评论