Open azl397985856 opened 2 years ago
滑窗
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.length()==0)return 0;
HashMap<Character,Integer> map =new HashMap<>();
int i=0,j=0,max=0;
while(j<s.length()){
char c = s.charAt(j);
if(map.containsKey(c)){
i =Math.max(i,map.get(c)+1);
}
max = Math.max(max,j-i+1);
map.put(c,j);
j++;
}
return max;
}
}
时间复杂度:O(n) 空间复杂度:O(n)
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
int n = s.length(), ans = 0, i = 0, j = 0;
for (; j < n; j++) {
char c = s.charAt(j);
if (map.containsKey(c) && map.get(c) >= i) {
i = map.get(c) + 1;
}
map.put(c, j);
ans = Math.max(ans, j - i + 1);
}
return ans;
}
}
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
给定一个字符串 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 由英文字母、数字、符号和空格组成
双指针,
左用来收缩
右用来前进( right 或者 i)
窗口大小的计算注意是否要加1?
窗口的长度是right - left +1
移动left是移动到那个坐标的下一个position
JavaScript Code:
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
const map = {};
let l = 0,
r = 0,
max = 0;
while (r < s.length) {
const pos = map[s[r]];
// 如果 s[r] 曾在 [l, r] 滑动窗口中出现
// 就收缩滑动窗口左侧,把 l 指针移动到 s[r] 上次出现的位置 + 1
if (pos >= l && pos <= r) l = pos + 1;
// 更新 s[r] 出现的位置
map[s[r]] = r;
// 计算滑动窗口大小
max = Math.max(max, r - l + 1);
// 滑动窗口继续右移扩张
r++;
}
return max;
};
复杂度分析
令 n 为数组长度。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int n = s.size();
if(n < 2) return n;
int ii, jj, ans;
unordered_map<char,int> h_cnt;
ans = 0;
h_cnt[s[0]] ++ ;
for(ii = 0, jj = 1; jj < n; ++ jj){
h_cnt[s[jj]] ++ ;
if(h_cnt[s[jj]] == 1){
ans = max(jj - ii + 1, ans);
continue;
}
while(s[ii] != s[jj]){
h_cnt[s[ii]] --;
++ ii;
}
h_cnt[s[ii]] --;
++ ii;
ans = max(ans, jj - ii + 1);
}
return ans;
}
};
not use hash table
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
if s == "":
return 0
start,end,ans = 0,0,1
lenstr = len(s)
while end < lenstr:
if s[end] not in s[start:end]:
ans = max(ans,end-start+1)
end += 1
else:
while s[end] in s[start:end]:
start += 1
return ans
# similar to 209.
# time complexity: O(N) 快慢指针各遍历一次
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
var maxLength = 0;
var startIndex = 0;
var storage = new Map();
for(let currentIndex =0; currentIndex<s.length;currentIndex++){
if(storage.has(s[currentIndex])){
startIndex = Math.max(startIndex,storage.get(s[currentIndex])+1);
}
storage.set(s[currentIndex],currentIndex);
maxLength = Math.max(maxLength,currentIndex-startIndex+1)
}
return maxLength;
};
// time O(n)
//space O(n)
哈希表 + 滑动窗口
var lengthOfLongestSubstring = function(s) {
let max = 0
let index = -1
let map = new Map()
for(let i = 0;i<s.length;i++){
if(map.has(s[i])){
index = Math.max(map.get(s[i]),index)
}
max = Math.max(max,i-index)
map.set(s[i],i)
}
return max
};
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
哈希表+滑动窗口,哈希集合+滑动窗口
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 写法一 哈希表+滑动窗口
# time n
# space n
# slidng window + hashMap
curlen = 0
maxlen = 0
# 定义左右指针
start, end = 0, 0
hashMap = {}
while end < len(s):
# 获取当前字符
char = s[end]
# corner case: "abba"
# 如果当前字符存在于哈希表并且hashMap[char](上次出现的idx)大于等于start
# 说明此时出现了重复字符 需要将start指向上一次出现重复字符的idx+1位置
if char in hashMap and hashMap[char] >= start:
start = hashMap[char] + 1
# 更新哈希表中最后一次出现char为end的位置
hashMap[char] = end
# 计算长度
curlen = end - start + 1
maxlen = max(curlen, maxlen)
end += 1
return maxlen
# eg: "abca"
# 当start = 0, end = 3
# {a:0, b:1, c:2} 代表字符a最后出现于idx0位置...,b...,c...
# 此时s[end]存在于哈希表中
# 先更新start = hashMap[s[end]] + 1 即 start = 1
# 再更新哈希表中s[end]字符最后一次出现的位置 即{a:3, b:1, c:2}
# 参考题解
# https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/python-zhu-bu-you-hua-cong-bao-li-fa-dao-6i34/
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 写法二 哈希集合+滑动窗口
# time n
# space n
# 滑动窗口
memo = set()
left = 0
max_len = 0
cur_len = 0
for i in range(0, len(s)):
cur_len += 1
# 发现重复
# 从集合中移出, 移动left, 减少当前长度
# 一直移动左边界直到s[i]不在memo中,因为有可能字符不在边界上
# corner case:
# "pwwkew"
while s[i] in memo:
memo.remove(s[left])
left += 1
cur_len -= 1
if cur_len > max_len:
max_len = cur_len
# 不重复就加入等待下次判断
memo.add(s[i])
return max_len
Hash table and Two pointers
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
res = 0
memo = collections.defaultdict(lambda:-1)
left = right = 0
while(right<len(s)):
pos = memo[s[right]]
if pos>=0 and pos >= left and pos <= right:
left = pos+1
memo[s[right]] = right
res = max(res, right-left+1)
right+=1
return res
Space: O(length of String) Time: O(N)
本质就是滑动窗口加哈希表,哈希表用于统计该字符是否出现过。 当发现有字符之前出现过,则将左指针的哈希值去掉,然后右移左指针。 最终找到一个最长子串
func lengthOfLongestSubstring(s string) int {
hashmap := make(map[byte]int)
i, out := 0, 0
for j := range s{
for hashmap[s[j]] != 0{
hashmap[s[i]]--
i++
}
hashmap[s[j]]++
out = max(out, j-i+1)
}
return out
}
func max(a, b int) int{
if a > b{
return a
}else{
return b
}
}
时间复杂度:O(n) 空间复杂度:O(n)
遍历字符串,一个指针先存到map中,保存值和下标,遍历的时候如果存在,那么更新J值,map保存当前元素,
res与i-j+1取最大值即可;
class Solution {
public int lengthOfLongestSubstring(String s) {
char[] c = s.toCharArray();
int j = 0;
int res = 0;
Map<Character,Integer> map = new HashMap<>();
for(int i = 0; i < c.length; i++){
if(map.containsKey(c[i])){
j = Math.max(j,map.get(c[i])+1);
}
map.put(c[i],i);
res = Math.max(res,i-j+1);
}
return res;
}
}
时间复杂度:O(n)
空间复杂度:O(size)
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
if (s.length == 0) return 0
if (s.length == 1) return 1
let res = 0,
temp,
tempstr
for (let i = 0; i < s.length - 1; i++) {
temp = 1
tempstr = s[i]
for (let j = i + 1; j < s.length; j++) {
if (tempstr.includes(s[j])) {
break
}
tempstr += s[j]
temp++
}
if (temp > res) {
res = temp
}
}
return res
}
func lengthOfLongestSubstring(s string) int {
m := map[byte]int{}
n := len(s)
rk, ans := 0, 0
for i := 0; i < n; i++ {
if i != 0 {
delete(m, s[i-1])
}
for rk < n && m[s[rk]] == 0{
m[s[rk]]++
rk++
}
ans = max(ans, rk - i)
}
return ans
}
func max(x, y int) int {
if x < y {
return y
}
return x
}
哈希表,遍历整个s,存到哈希表里,一旦出现重复就记录重复的值位置为开始,取最大
public int lengthOfLongestSubstring(String s) {
if(s.length()<2){
return s.length();
}
Map<Character,Integer> map =new HashMap<>();
int state = -1;
int max = 0;
for (int i = 0; i < s.length(); i++) {
state = Math.max(map.getOrDefault(s.charAt(i),state),state);
map.put(s.charAt(i),i);
max = Math.max(max,i-state);
}
return max;
}
T:O(N) S:O(n)
def lengthOfLongestSubstring(self, s: str) -> int:
ans = 0
d = {}
start = 0
for end, v in enumerate(s):
if v in d.keys():
start = max(d.get(v) + 1, start)
ans = max(ans, end - start + 1)
d[v] = end
return ans
idea: dp. Use an array with size n to store at the index i, the length of the nonrepeated string. Then return the max of this array. Each time to write in arr[i], check if charAt(i) is the same as previous characters from i-1. If not, arr[i]=arr[i-1]+1; if repetition occurs, use a variable start to record the position where the last nonrepetitive substring ends. Time: O(n^2) Space: O(n)
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.isEmpty())
return 0;
int[] map=new int[s.length()];
int start=0;
map[0]=1;
for(int i=1;i<s.length();i++) {
map[i]=map[i-1]+1;
for(int j=i-1;j>=start;j--) {
if(s.charAt(j)==s.charAt(i)) {
map[i]=i-j;
start=j+1;
}
}
}
int max=map[0];
for(int n:map) {
if(n>max)
max=n;
}
return max;
}
}
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
current_len = 0
max_len= 0
start = 0
end = 0
hashmap = {}
while end < len(s):
char = s[end]
if char in hashmap.keys() and hashmap[char] >= start:
start = hashmap[char] +1
hashmap[char] = end
current_len = end - start + 1
max_len = max(max_len, current_len)
end += 1
return max_len
时间复杂度: O(N) 空间复杂度:O(N)
哈希表+双指针
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
result = 0
left = 0
seen = set()
for right in range(len(s)):
while s[right] in seen:
seen.remove(s[left])
left += 1
seen.add(s[right])
result = max(result, right - left + 1)
return result
双指针+哈希表
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int n=s.size();
if(n<=1)
return n;
int i=0,j=1,max=-1;
unordered_map<char,int>m;
m[s[0]]++;
while(j<n)
{
if(m[s[j]])
m[s[i++]]=0;
else
m[s[j++]]=1;
if(j-i>max)
max=j-i;
}
return max;
}
};
复杂度分析
var lengthOfLongestSubstring = function (s) {
let res = 0;
let temp = "";
for (let i = 0; i < s.length; i++) {
let idx = temp.indexOf(s[i]);
if (idx == -1) {
temp += s[i];
res = Math.max(res, temp.length);
} else {
temp = temp.slice(idx + 1) + s[i];
}
}
return res;
};
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
res = 0
i, j = 0, 0
chars = set()
while j<len(s):
if s[j] not in chars:
chars.add(s[j])
else:
res = max(res, j-i)
while s[i]!=s[j] and i<j:
chars.remove(s[i])
i += 1
i += 1
j += 1
return max(res, j-i)
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
int max = 0;
int start = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(map.containsKey(c)) {
int length = i - start;
max = Math.max(max, length);
start = Math.max(map.get(c) + 1, start);
}
map.put(c, i);
}
max = Math.max(s.length() - start, max);
return max;
}
}
时间复杂度: O(N) N为字符串长度 空间复杂度: O(M) hash表存储的字符长度。
C++ Code:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int res = 0;
unordered_map<char, int> um;
int left = 0;
for (int right = 0; right < s.length(); ++right) {
if (um.find(s[right]) != um.end()) {
left = max(left, um[s[right]] + 1);
}
um[s[right]] = right;
res = max(res, right - left + 1);
}
return res;
}
};
令 n 为数组长度。
滑动窗口
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left = 0
right = 0
res_len = 0
for i in range(len(s)):
if s[i] not in s[left:right]:
right += 1
res_len = max(res_len, right-left)
else:
while s[i] in s[left:right]:
left += 1
right += 1
return res_len
O(n)
O(n)
/**
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
tmp = set()
right, ans = -1, 0
for i in range(len(s)):
if i != 0:
tmp.remove(s[i-1])
while right + 1 < len(s) and s[right +1] not in tmp:
tmp.add(s[right +1])
right += 1
ans = max(ans , right - i + 1)
return ans
3. 无重复字符的最长子串
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
滑动窗口
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 哈希集合,记录每个字符是否出现过
occ = set()
n = len(s)
# 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
rk, ans = -1, 0
for i in range(n):
if i != 0:
# 左指针向右移动一格,移除一个字符
occ.remove(s[i - 1])
while rk + 1 < n and s[rk + 1] not in occ:
# 不断地移动右指针
occ.add(s[rk + 1])
rk += 1
# 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = max(ans, rk - i + 1)
return ans
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() < 1) {
return 0;
}
int res = 1;
for (int i = 0; i < s.length(); i++) {
HashSet<Character> set = new HashSet();
set.add(s.charAt(i));
for (int j = i + 1; j < s.length(); j++) {
if (set.contains(s.charAt(j))) {
break;
}
int len = j - i + 1;
res = Math.max(res, len);
set.add(s.charAt(j));
}
}
return res;
}
}
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() < 1) {
return 0;
}
int res = 0, left = 0, right = 0, length = 0;
HashSet<Character> set = new HashSet();
while (right < s.length()) {
char c = s.charAt(right);
if (!set.contains(c)) {
set.add(c);
length = right - left + 1;
res = Math.max(res, length);
right++;
} else {
set.remove(s.charAt(left));
left++;
}
}
return res;
}
}
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
left = 0 # 左指针 起始点0
find = set()
max_len = 0
curr_len = 0
for i in range(len(s)):
curr_len += 1 # 列表长度+=1
while s[i] in find: #当有重复项时(元素没有加入)
find.remove(s[left]) # 将list中的left element移除
left += 1 #指针向右移动
curr_len -= 1 #因为减少element list长度-1
while curr_len > max_len:
max_len = curr_len
find.add(s[i]) #再把当前元素加入
return max_len
Complexicity: O(n^2)
Two pointers to represent the start and end indices of the substring. Go through the string and use api indexof to check if is a repeated character. If is, update the start index to that index+1. Update the maximum value every time.
class Solution {
public int lengthOfLongestSubstring(String s) {
int j = 0;
int res = 0;
for (int i = 0; i < s.length(); ++i) {
String sub = s.substring(j, i);
int index = sub.indexOf(s.charAt(i));
if (index != -1) {
j = j + index + 1;
}
res = Math.max(res, i - j + 1);
}
return res;
}
}
class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;
Map<Character,Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
// 已经存在相同的key了,记录当前的map大小,并将i定义到之前的i+1的位置
if(map.containsKey(s.charAt(i))){
max = Math.max(max,map.size());
i = map.get(s.charAt(i))+1;
map.clear();
}
map.put(s.charAt(i),i);
}
// 遍历完之后,再判断map中剩下的长度是否大于之前的长度
max = Math.max(max,map.size());
return max;
}
}
复杂度分析
— 时间复杂度:O(n),其中n为字符串长度。
— 空间复杂度:O(n),字符串存到hashMap
题目名称
题目链接 https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
题目思路 滑动窗口
code for Python3 class Solution: def lengthOfLongestSubstring(self, s: str) -> int:
occ = set()
n = len(s)
# 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
rk, ans = -1, 0
for i in range(n):
if i != 0:
# 左指针向右移动一格,移除一个字符
occ.remove(s[i - 1])
while rk + 1 < n and s[rk + 1] not in occ:
# 不断地移动右指针
occ.add(s[rk + 1])
rk += 1
# 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = max(ans, rk - i + 1)
return ans
复杂度分析 时间复杂度: O(N) 空间复杂度: O(N)
int lengthOfLongestSubstring(char * s){
char *head, *tail, *p;
head = tail = s;
int max = 0;
for(; *tail != '\0'; tail++)
{
for(p=head; p<tail; p++)
if(*p == *tail)
{
head = p + 1;
break;
}
if(max < tail - head + 1)
max = tail - head + 1;
}
return max;
}
思路:
int lengthOfLongestSubstring(string s) {
int left = 0, right = 0;
unordered_set<char> st;
int res = 0;
for (right = 0; right < s.length(); ++right){
if (st.count(s[right])){
res = max(res, right - left);
while (s[left] != s[right]){
st.erase(s[left]);
++left;
}
++left;
}
else{
st.emplace(s[right]);
}
}
return max(res, right - left);
}
复杂度:
滑动窗口+HashSet的不重复元素哈希表集合
class Solution {
public int lengthOfLongestSubstring(String s) {
int l = s.length();
int res = 0;
int right=0,left=0;
Set<Character> set = new HashSet();
while(left < l && right < l){
if(set.contains(s.charAt(right))){
set.remove(s.charAt(left++)); //如果窗口中有重复,窗口左侧侧向右滑动
}else{
set.add(s.charAt(right++));//如果窗口中无重复,窗口右侧向右滑动
res=Math.max(res,right-left);//记录当前最大长度
}
}
return res;
}
}
时间复杂度:O(N)
空间复杂度:O(logN)
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
if len(s)<=1:
return len(s)
left = 0
right = 1
result = 0
while right<len(s):
if s[right] not in s[left:right]:
right += 1
else:
index= s.index(s[right])
result = max(result,right-left)
s = s[index+1:]
right -= index+1
result = max(result,len(s))
return result
使用hashmap,key为字符串的值,value为其下标值,使用一个变量记录这个字符串最右边的坐标值,如果map中有这个,则给取右值的i赋值之后赛到map,如果没有,直接塞入,然后每次循环都使用res记录最大距离,最后返回
public static int lengthOfLongestSubstring(String s) {
int res=0,i=0,j;
Map<Character,Integer> map=new HashMap<>();
for(j=0;j<s.length();j++){
if(map.containsKey(s.charAt(j))){
i=Math.max(map.get(s.charAt(j)),i);
}
res=Math.max(res,j-i+1);
map.put(s.charAt(j),j+1);
}
return res;
}
···
#### 复杂度分析
时间复杂度:O(N)
Solution 1 : We use set and sliding window
Solution 2: We use hashmap and sliding window. We store the char as the key and the value will be the last seen index of the char.
Solution 1
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left=0
visited=set()
max_length=0
for right in range(len(s)):
while s[right] in visited:
visited.remove(s[left])
left+=1
visited.add(s[right])
max_length=max(max_length,right-left+1)
return max_length
Solution 2
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
charMap={}
left=0
result=0
for right in range(len(s)):
if s[right] in charMap and charMap[s[right]] >= left:
left = charMap[s[right]] + 1
charMap[s[right]] = right
result=max(result,right-left+1)
return result
Time:O(n)
Space:O(n)
Time: O(n)
Space: O(n)
https://leetcode.com/problems/longest-substring-without-repeating-characters
Easy
Medium
Scan the string. Use Hashtable to keep the longest substring so far. If any character exists in the hashtable, remove all elements whose position before the character and update the new character position.
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
d = {}
max_len = 0
d_head = 0
for i in range(len(s)):
if s[i] in d:
j = d_head
pos_i = d[s[i]]
while j < pos_i +1:
del d[s[j]]
j += 1
d_head = j
d[s[i]] = i
else:
d[s[i]] = i
max_len = max(max_len, len(d))
return max_len
时间复杂度: O(N) 空间复杂度:O(N)
··· class Solution: def lengthOfLongestSubstring(self, s: str) -> int: chars = [0] * 128
left = right = 0
res = 0
while right < len(s):
r = s[right]
chars[ord(r)] += 1
while chars[ord(r)] > 1:
l = s[left]
chars[ord(l)] -= 1
left += 1
res = max(res, right - left + 1)
right += 1
return res
··· ·O(n)·
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) return 0;
Set<Character> set = new HashSet<>();
int start = 0;
int end = 0;
int max = 0;
while (end < s.length()) {
char ch = s.charAt(end++);
while (set.contains(ch)) {
set.remove(s.charAt(start++));
}
set.add(ch);
max = Math.max(max, end - start);
}
return max;
}
}
时间:O(n)
空间:O(n)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
slow = 0
dict_s = dict()
ans = 0
for i,v in enumerate(s):
if v in dict_s:
slow = max(slow, dict_s[v]+ 1)
ans = max(ans, i - slow + 1 )
dict_s[v] = i
return ans
t: o(n) s: O(N)
输入: 一个字符串 输出: 字符串中, 最长不包含重复字符字串的长度
public int lengthOfLongestSubstring(String s) {
HashMap <Character,Integer> map = new HashMap<Character,Integer>();
int right = -1, ans = 0;
int N = s.length();
for( int i =0 ; i<N;++i){
if(i!=0){
map.remove(s.charAt(i-1));
}
while(right+1<N && !map.containsKey(s.charAt(right+1))){
map.put(s.charAt(right+1),map.getOrDefault(s.charAt(right+1),0)+1);
right++;
}
ans = Math.max(ans, right - i + 1);
}
return ans;
}
维护一个HashMap依次记录每个char出现的位置
当char存在于HashMap中,改变start位置
class Solution {
public int lengthOfLongestSubstring(String s) {
int res = 0;
Map<Character, Integer> map = new HashMap<>();
for (int i = 0, start = 0; i < s.length(); i++) {
char c = s.charAt(i);
// "abbac"
// index = 2, c = 'b', start = 2
// index = 3, c = 'a', start = max(2, 1)
start = map.containsKey(c) ? Math.max(start, map.get(c) + 1) : start;
map.put(c, i);
res = Math.max(res, i - start + 1);
}
return res;
}
}
哈希+滑动窗口。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
letters = set()
l = r = 0
res = 0
while l < len(s) and r < len(s):
if s[r] not in letters:
letters.add(s[r])
r += 1
else:
letters.remove(s[l])
l += 1
res = max(res, len(letters))
return res
时间:O(N) N为字符串长度 空间:O(N)
class Solution {
public:
//滑动窗口
//利用双指针维护滑动窗口大小;
//right指针只管向前依次遍历
//left指针需遍历其起点到right指针的前一个的字符;
//left的起点确定就是上一个重复出现的right的位置
//设置max,用来记录整个过程出现的最大长度
int lengthOfLongestSubstring(string s) {
int max_cnt = 0, cnt = 0, left = 0, right = 0;
while (right < s.size()) {
char c = s[right];
for (int i = left; i < right; i ++) {
if (s[i] == c) {
left = i + 1;
cnt = right - left;
break;
}
}
cnt ++;
max_cnt = max(max_cnt, cnt);
right ++;
}
return max_cnt;
}
};
/**
* @param {string} s
* @return {number}
*/
const lengthOfLongestSubstring = function(s) {
const seenIdx = new Map();
let maxLen = 0;
let start = 0;
for (let i = 0; i < s.length; i++) {
if (seenIdx.has(s[i])) {
start = Math.max(start, seenIdx.get(s[i]) + 1);
}
seenIdx.set(s[i], i);
maxLen = Math.max(maxLen, i - start + 1);
}
return maxLen;
};
思路
暴力循环,对字符串进行扫描,用set存储每轮是否有重复字符串,出现重复字符串跳往下一轮,长度计算用第二个循环指针减去第一个循环指针位置+1
代码
class Solution {
public int lengthOfLongestSubstring(String s) {
int ret = 0;
for (int i = 0; i < s.length(); i++) {
HashSet<Character> set = new HashSet<>();
for (int j = i; j < s.length(); j++) {
if (set.contains(s.charAt(j))){
break;
}
set.add(s.charAt(j));
ret = Math.max(ret,j - i + 1);
}
}
return ret;
}
}
复杂度
时间复杂度:O(N^2),N为字符串长度
空间复杂度:O(1)
思路
滑动窗口,哈希表,维护一个滑动窗口,遇到字符存进map里并记录下标,如果再下次遇到map中存在的字符,将左边的窗口收缩(指针移动),将左边的指针移动到上一次遇到该字符位置+1.注意在移动左边指针时,保证移动位置在滑动窗口中。如果不在则更新map里该字符的位置。
代码
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> map = new HashMap<>();
int max_len = 0,left = 0,right = 0;
while (right < s.length()){
if (map.containsKey(s.charAt(right))){
int last_pos = map.get(s.charAt(right));
if (last_pos >= left && last_pos <= right){
left = last_pos + 1;
}
}
max_len = Math.max(max_len,right - left + 1);
map.put(s.charAt(right),right);
right++;
}
return max_len;
}
}
复杂度
时间复杂度:O(N),N为字符串长度
空间复杂度:O(S),S为map中字符集的个数
哈希
let max = 0;
let start = 0;
let obj = new Map();
for(let i = 0; i < s.length; i++){
const str = s.charAt(i);
if(obj.has(str)){
start = Math.max(obj.get(str)+1,start);
}
max = Math.max(max,i-start+1);
obj.set(str,i);
}
return max;
滑动窗口
const lengthOfLongestSubstring = s => {
const occ = new Set();
const n = s.length;
let rk = -1,
ans = 0;
for (let i = 0; i < n; ++i) {
if (i !== 0) {
occ.delete(s.charAt(i - 1));
}
while (rk + 1 < n && !occ.has(s.charAt(rk + 1))) {
occ.add(s.charAt(rk + 1));
++rk;
}
}
return ans;
}
3. 无重复字符的最长子串
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
前置知识
题目描述
示例 1:
输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb" 输出: 1 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。