[LeetCode] 3. 无重复字符的最长子串
Posted lijiong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode] 3. 无重复字符的最长子串相关的知识,希望对你有一定的参考价值。
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是?"wke",所以其长度为 3。
? 请注意,你的答案必须是 子串 的长度,"pwke"?是一个子序列,不是子串。
分析
-
双指针,通过set保存字符,需考虑第二个指针到最后的情况
-
滑动窗口,若某元素在 [i, j) 范围内有重复字符,则将i变为该元素在范围内索引加1
解法
解法一
-
双指针,通过set保存字符
-
时间复杂度O(n)
-
空间复杂度O(min(m,n)),m和n分别为字符集大小和字符串大小
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.length() == 0) return 0;
char[] arr = s.toCharArray();
int max = 1;
// i为每个子串的起点
for(int i = 0; i < arr.length-1; i++){
// 保存字符
HashSet<Character> set = new HashSet<>();
set.add(arr[i]);
// j为每个子串的终点
for(int j = i+1; j < arr.length; j++){
if(set.contains(arr[j])){
if(j - i > max){
max = j - i;
}
break;
}
// j到最后的情况
if(j == arr.length-1){
if(j - i + 1 > max){
max = j - i + 1;
}
break;
}
set.add(arr[j]);
}
}
return max;
}
}
//class Test{
// public static void main(String[] args) {
// Solution s = new Solution();
// int res = s.lengthOfLongestSubstring("abcabcbb");
// System.out.println(res);
// }
//}
解法二
-
右指针每移动一次,检查左指针到右指针有没有和右指针重复的,若有,将左指针变为重复索引加1
-
时间复杂度O(n)
-
空间复杂度O(1)
class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;
char[] chars = s.toCharArray();
int left = 0;
for (int right = 0; right < s.length(); right++) {
for (int i = left; i < right; i++) {
if (chars[i] == chars[right]) {
// left至right-1为无重复子串,长度为right-left
max = Math.max(max, right - left);
left = i + 1;
break;
}
}
}
// max以重复字符为判断,需考虑无重复情况
return Math.max(s.length() - left, max);
}
}
解法三
-
滑动窗口
-
时间复杂度O(n)
-
空间复杂度O(min(m,n))
class Solution {
public int lengthOfLongestSubstring(String s) {
int ans = 0;
// k:v为字符:索引
Map<Character, Integer> map = new HashMap<>();
for (int left = 0, right = 0; right < s.length(); right++) {
if (map.containsKey(s.charAt(right))) {
// 若重复字符不在当前的子串中(索引小于left),left保持不变
// 若重复字符在当前子串中,left变为子串中该字符索引加1
left = Math.max(map.get(s.charAt(right)) + 1, left);
}
ans = Math.max(ans, right - left + 1);
map.put(s.charAt(right), right);
}
return ans;
}
}
解法四
-
滑动窗口+ASCII128
-
时间复杂度O(n)
-
空间复杂度O(m),m为字符集大小
class Solution {
public int lengthOfLongestSubstring(String s) {
int ans = 0;
// 存储元素为字符在字符串中的最新位置
Integer[] index = new Integer[128];
for (int left = 0, right = 0; right < s.length(); right++) {
// 相应值不为null,则字符重复
if(index[s.charAt(right)] != null){
// 若重复字符不在当前的子串中(索引小于left),left保持不变
// 若重复字符在当前子串中,left变为子串中该字符索引加1
left = Math.max(index[s.charAt(right)] + 1, left);
}
ans = Math.max(ans, right - left + 1);
index[s.charAt(right)] = right;
}
return ans;
}
}
以上是关于[LeetCode] 3. 无重复字符的最长子串的主要内容,如果未能解决你的问题,请参考以下文章