Open azl397985856 opened 2 years ago
双指针,哈希表存窗口内各元素出现的次数。但实际上看了官方题解后恍然大悟,哈希表存各元素上一次出现的位置会更好,这样同样能达成比较右指针前进时遇到的元素是否是重复元素的目的,同时能让左指针移动得更快
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if s == "": return 0
left, right = 0, 0
total_len = len(s)
res = 0
hash_map = collections.defaultdict(int)
while right != total_len:
if hash_map[s[right]] == 0:
hash_map[s[right]] += 1
right += 1
if right == total_len:
res = max(res, right - left)
else:
res = max(res, right - left)
hash_map[s[left]] -= 1
left += 1
return res
利用集合的不重复性,移动窗口,将重复的元素移除,记录遍历过程窗口的最大长度。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
lookup = set() # 确保元素唯一性的集合
max_len, cur_len = 0, 0
left = 0 # 数组不重复的位置
for c in s:
cur_len += 1
while c in lookup:
lookup.remove(s[left])
left += 1
cur_len -= 1
lookup.add(c)
max_len = max(max_len, cur_len)
return max_len
[TOC]
Longest Substring Without Repeating Characters
使用hashset来追踪最长的不重复子串。使用双指针,判断指针内的字符是否在hashset内重复,如果不重复,加入hashset,快指针继续向下移动,如果重复hashset删掉慢指针元素,慢指针向下移动,直到可以加入新的快指针的元素
class Solution {
public int lengthOfLongestSubstring(String s) {
int i=0, j=0, max=0;
Set<Character> set = new HashSet<>();
while (j < s.length()){
if (!set.contains(s.charAt(j))){
set.add(s.charAt(j++));
max = Math.max(max, set.size());
}else{
set.remove(s.charAt(i++));
}
}
return max;
}
}
复杂度分析
时间复杂度 : O(n)
空间复杂度 : O(s) 字符串长度
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let occ = new Set()
const n = s.length
let rk = -1
let 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
}
ans = Math.max(ans, rk - i + 1)
}
return ans
};
hashSet存放子串字符,重复时清空重新开始存放,更新最大长度
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s == null || s.equals("")){
return 0;
}
int maxLen = 0;
Set<Character> set = new HashSet();
int i = 0;
int j = 0;
Map<Character, Integer> map = new HashMap();
char[] chars = s.toCharArray();
while(i < chars.length && j < chars.length){
char cc = chars[i];
map.put(cc, i);
for(j = i+1; j < chars.length; j ++){
char c = chars[j];
if(map.containsKey(c)){
maxLen = maxLen > map.size() ? maxLen : map.size();
i = map.get(c)+1;
map.clear();
break;
}else{
map.put(c, j);
}
}
}
maxLen = maxLen > map.size() ? maxLen : map.size();
return maxLen;
}
}
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
hashset = set()
l = r = 0
ans = 0
while r < len(s):
if s[r] in hashset:
hashset.remove(s[l])
l += 1
else:
hashset.add(s[r])
r += 1
ans = max(ans, len(hashset))
return ans
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() == 0) return 0;
Map<Character, Integer> map = new HashMap<>();
int maxlength = 0;
int left = 0;
for(int i = 0;i < s.length();i++) {
if (map.containsKey(s.charAt(i))) {
left = Math.max(left, map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i), i);
maxlength = Math.max(maxlength, i - left + 1);
}
return maxlength;
}
}
【day22】 3. 无重复字符的最长子串
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
方法:哈希表+滑动窗口
代码:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
length = 0
hasmap = dict()
left, right = 0, 0
#1个字符返回
if len(s) < 1:
return len(s)
hasmap[s[left]] = 0
while right < len(s):
#判断右指针指向的字符是否在当前滑动窗口中有重复
if s[right] in s[left:right]:#说明重复
length = max(length, right-left)
left = hasmap[s[right]] + 1 #找到字符以前出现的位置,向前走一步
else:
length = max(length, right-left) #更新维护的不重复最大字串
hasmap[s[right]] = right
right = right + 1
length = max(length, right - left)
return length
复杂度分析:
遍历数组并通过哈希表保存[char,index],如果发现有重复元素就更新max,反之就继续遍历
Java Code:
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);
Integer idx = map.get(c);
if(idx != null && idx >= start){
max = Math.max(max, i - start);
start = idx + 1;
}
map.put(c, i);
}
return Math.max(s.length() - start,max);
}
}
复杂度分析
javascript
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
if (s === '') return 0
let left = 0
const map = {}
let max = 0
for (let i = 0; i < s.length; i++) {
const char = s[i]
if (char in map) {
left = Math.max(left, map[char])
}
// 存除这个节点的开始坐标
// 是出现重复时,上面代码会把左指针向右移动了
map[char] = i + 1
max = Math.max(max, i - left + 1)
}
return max
};
// @lc code=end
JavaScript Code:
/**
* @param {string} s
* @return {number}
*/
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function (str) {
let myMap = new Map();
let maxLen = 0,
len = str.length;
for (let i = 0, j = 0; j < len; j++) {
if (myMap.has(str.charAt(j))) {
i = Math.max(myMap.get(str.charAt(j)), i);
}
maxLen = Math.max(maxLen, j - i + 1);
myMap.set(str.charAt(j), j + 1);
}
return maxLen;
};
复杂度分析
令 n 为数组长度。
思路 定义一个 map 数据结构存储 (k, v),其中 key 值为字符,value 值为字符位置 +1,加 1 表示从字符位置后一个才开始不重复 我们定义不重复子串的开始位置为 start,结束位置为 end 随着 end 不断遍历向后,会遇到与 [start, end] 区间内字符相同的情况,此时将字符作为 key 值,获取其 value 值,并更新 start,此时 [start, end] 区间内不存在重复字符 Java
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>();
for (int end = 0, start = 0; end < n; end++) {
char alpha = s.charAt(end);
if (map.containsKey(alpha)) {
start = Math.max(map.get(alpha), start);
}
ans = Math.max(ans, end - start + 1);
map.put(s.charAt(end), end + 1);
}
return ans;
}
}
时间复杂度:O(n)
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) {
return 0;
}
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left+1);
}
return max;
}
}
滑动窗口
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> occ = new HashSet<Character>();
int n = s.length();
int rk = -1, ans = 0;
for (int i = 0; i < n; ++i) {
if (i != 0) {
occ.remove(s.charAt(i - 1));
}
while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
occ.add(s.charAt(rk + 1));
++rk;
}
ans = Math.max(ans, rk - i + 1);
}
return ans;
}
}
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public int lengthOfLongestSubstring(String s) {
int l = s.length();
int start = 0;
int right = 0;
HashSet
思路: 利用set 集合判断是否存在重复字符..如果存在 就从左删除一个字符,否则从右侧添加一个字符
var lengthOfLongestSubstring = function (s) {
// Set集合,记录每个字符是否出现过
const setMap = new Set();
const strLen = s.length;
let rightIndex = -1
let resultLength = 0;
for (let i = 0; i < strLen; ++i) {
if (i != 0) {
// 判断元素如果存在,删除元素,同时移动左侧元素
setMap.delete(s.charAt(i - 1));
}
// 移动右侧的元素
while (rightIndex + 1 < strLen && !setMap.has(s.charAt(rightIndex + 1))) {
setMap.add(s.charAt(rightIndex + 1));
++rightIndex;
}
// 计算每次set中的子串长度即可
resultLength = Math.max(resultLength, rightIndex - i + 1);
}
return [resultLength];
};
时间复杂度:O(N)
空间复杂度:O(N)
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
const length = s.length
if (length <= 1) return length
let res = 0
for (let i = 0; i < length; i++) {
let map = new Map()
for (let j = i; j < s.length; j++) {
if (map.has(s[j])) break
map.set(s[j], true)
res = Math.max(res, j - i + 1)
}
}
return res
};
class Solution: def lengthOfLongestSubstring(self, s: str) -> int: if not s:return 0 left = 0 lookup = set() n = len(s) max_len = 0 cur_len = 0 for i in range(n): cur_len += 1 while s[i] in lookup: lookup.remove(s[left]) left += 1 cur_len -= 1 if cur_len > max_len:max_len = cur_len lookup.add(s[i]) return max(len)
class Solution
{
public:
int lengthOfLongestSubstring(string s)
{
std::unordered_map<char, int> aMap;
size_t lft{ 0 };
size_t rht{ 0 };
size_t res{ 0 };
while (rht < s.size()) {
char &rht_c = s[rht];
if (aMap.count(rht_c) == 0) {
aMap.emplace(rht_c, 1);
} else {
aMap[rht_c]++;
}
rht++;
while (aMap[rht_c] > 1) {
char lft_c = s[lft];
lft++;
aMap[lft_c]--;
}
res = std::max(res, rht - lft);
}
return res;
}
};
Sliding window 通常用于数组和字符串,移动一个端点,快速地确定另一个端点
logic:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int n = s.size();
int len = 0;
int i = 0;
map<char, int> window;
for(int j = 0; j<n; j++)
{
if(window.find(s[j]) != window.end())
{
len = max(len, j - i);
i = max(i, window[s[j]]+1);
}
// note that s[j]'s index should be updated anyway
window[s[j]] = j;
}
len = max(len, n - i);
return len;
}
};
Complexity Analysis: T: O(n) S: O(n)
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" 是一个子序列,不是子串。
弄一个集合,集合中如何出现重复元素,从左向右删除字符,直到集合不重复为止
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:return 0
left = 0
lookup = set()
n = len(s)
max_len = 0
cur_len = 0
for i in range(n):
cur_len += 1
while s[i] in lookup:
lookup.remove(s[left])
left += 1
cur_len -= 1
if cur_len > max_len:max_len = cur_len
lookup.add(s[i])
return max_len
时间复杂度:O(N) 空间复杂度:O(N)
LC 3. Longest Substring Without Repeating Characters
Ideas
comment Runtime: 80 ms, faster than 45.42%
python代码
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
if n <= 1:
return n
window = set()
max_len = 0
left, right = 0,0
while right < n:
if s[right] not in window:
max_len = max(max_len, right-left+1)
window.add(s[right])
right += 1
else:
window.remove(s[left])
left +=1
return max_len
复杂度分析
利用哈希表+滑动窗口;
用双指针定义一个滑动窗口,右指针指向的字符不在窗口中重复时,右指针进一步;遇到重复字符,左指针收缩到字符上次出现的位置。 使用哈希表记录每一个字符出现的最新位置 使用单独一个变量存储窗口的最大长度
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() == 0){
return 0;
}
//res as maximum length, left is left pointer
int res = 0, left = 0;
Map<Character, Integer> map = new HashMap<>();
//right is right pointer
for (int right = 0; right < s.length(); right++){
char curr = s.charAt(right);
if (map.containsKey(curr)){
left = Math.max(left, map.get(curr) + 1);
}
//label begins from 0, so +1 to get numbers.
res = Math.max(res, right - left + 1);
map.put(curr, right);//update the new position of repeat elements
}
return res;
}
}
java
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left+1);
}
return max;
}
}
var lengthOfLongestSubstring = function(s) {
// 哈希集合,记录每个字符是否出现过
const occ = new Set();
const n = s.length;
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
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;
}
// 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = Math.max(ans, rk - i + 1);
}
return ans;
};
哈希表+滑动窗口
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
dic = set()
ans = 0
left = right = 0
while right<len(s):
if s[right] in dic:
dic.remove(s[left])
left += 1
else:
dic.add(s[right])
right += 1
ans = max(right-left,ans)
return ans
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);
Integer idx = map.get(c);
if(idx != null && idx >= start){
max = Math.max(max, i - start);
start = idx + 1;
}
map.put(c, i);
}
return Math.max(s.length() - start,max);
}
}
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int low = 0, high = 0, count = 0;
Set<Character> window = new HashSet();
while (high < s.length()) {
while (high < s.length() && !window.contains(s.charAt(high))) {
window.add(s.charAt(high));
high++;
}
count = Math.max(count, high - low);
//expand high, move low
while (high < s.length() && s.charAt(low) != s.charAt(high)) {
window.remove(s.charAt(low));
low++;
}
low++;
high++;
}
return count;
}
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left+1);
}
return max;
}
}
时间复杂度:O(N) 空间复杂度:O(N)。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 哈希集合,记录每个字符是否出现过
unordered_set
思路:使用滑动窗口,判断当前字符串不在滑动窗口中的话,就移动右指针,如果在的话,就移动左指针,直到将滑动窗口中不含有当前的字符。记录滑动窗口最大时候的字串。
class Solution { public int lengthOfLongestSubstring(String s) { int size=s.length(); int i=0,j=0; int res=0; HashSet<Character> hashSet = new HashSet<>(); for(;j<size;j++){ Character temp=s.charAt(j); if(!hashSet.contains(temp)){ hashSet.add(temp); res=hashSet.size()>res?hashSet.size():res; }else{ while(hashSet.contains(temp)){ hashSet.remove(s.charAt(i)); i++; if(i==j)break; } hashSet.add(s.charAt(j)); } } return res; } }
滑动窗口,双指针+字典
时间:n^2
空间:n 或者 str长度
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left,right,maxl = 0,0,0
hashmap = {}
for right in range(len(s)):
letter = s[right]
if s[right] in hashmap:
left = max(hashmap[letter]+1,left)
long = right - left +1
maxl = max(maxl, long)
hashmap[letter] = right
return maxl
哈希表+滑动窗口
/**
* @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
};
时间复杂度:O(n)
空间复杂度:O(n)
sliding window + hashmap hashmap 用来存string中每个字母的位置, 以及检查遍历到的新的元素是否存在于现有的substring当中。如果存在,则要更新left pointer,更新到的位置应为新元素的原有位置的后一位。最大的长度为right pointer- left pointer + 1
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) <= 1:
return len(s)
d = {}
i = 0
max_len = 0
for j in range(len(s)):
if s[j] not in d:
d[s[j]] = j
max_len = max(max_len, j - i + 1)
continue
else:
i = max(d[s[j]] + 1, i)
max_len = max(max_len, j - i + 1)
d[s[j]] = j
return max_len
时间复杂度: O(n) 空间复杂度:O(n)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) == 0 or len(s) == 1: return len(s)
p1 = 0
p2 = 1
chars = set()
chars.add(s[p1])
if s[p2] in chars:
p1 = p2
else:
chars.add(s[p2])
lenLongestSubstring = len(chars)
while p2+1<len(s):
if s[p2+1] not in chars:
p2+=1
chars.add(s[p2])
elif s[p2+1] == s[p2]:
p2 += 1
p1 = p2
chars.clear()
chars.add(s[p2])
else:
while p1<p2 and s[p2+1] in chars:
chars.remove(s[p1])
p1+=1
p2 += 1
chars.add(s[p2])
lenLongestSubstring = max(lenLongestSubstring, len(chars))
return lenLongestSubstring
class Solution {
public int lengthOfLongestSubstring(String s) {
int[] asciiArray = new int[128];
int len = 0;
for(int i = 0, j = 0; j < s.length(); j++){
//记录新的位置
i = Math.max(asciiArray[s.charAt(j)], i);
//相当于一个hashmap了
asciiArray[s.charAt(j)] = j+1;
//每次记录长度,比较
len = Math.max(len, j - i + 1);
}
return len;
}
}
class Solution(object):
def lengthOfLongestSubstring(self, s):
res = 0
for i in range(len(s)):
seen = dict()
for j in range(i,len(s)):
if s[j] not in seen:
seen[s[j]] = 1
res = max(res, j - i + 1)
else:
break
return res
T: n^2 S: n
class Solution(object):
def lengthOfLongestSubstring(self, s):
i = 0
j = 0
res = 0
seen = {}
while i < len(s):
if s[i] in seen:
j = max(j,seen[s[i]] + 1)
# 取max是为了防止尾指针倒退 - 比如"tmmzuxt"中头指针指到最后一个t时
# 防止尾指针指向index=1
seen[s[i]] = i # 更新seen里index的值
res = max(res, i - j + 1)
i += 1
return res
T: n S: n
(mark 先抄作业)
const lengthOfLongestSubstring = function (s) {
// keeps track of the most recent index of each letter.
const seen = new Map();
// keeps track of the starting index of the current substring.
let start = 0;
// keeps track of the maximum substring length.
let maxLen = 0;
for (let i = 0; i < s.length; i++) {
// if the current char was seen, move the start to (1 + the last index of this char)
// max prevents moving backward, 'start' can only move forward
if (seen.has(s[i])) start = Math.max(seen.get(s[i]) + 1, start);
seen.set(s[i], i);
// maximum of the current substring length and maxLen
maxLen = Math.max(i - start + 1, maxLen);
}
return maxLen;
};
Python3 Code:
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: # rk一直+1 in the while loop
# 不断地移动右指针
occ.add(s[rk + 1])
rk += 1
# 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = max(ans, rk - i + 1)
return ans
# 2
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:return 0
left = 0
lookup = set()
n = len(s)
max_len = 0
cur_len = 0
for i in range(n):
cur_len += 1
while s[i] in lookup:
lookup.remove(s[left])
left += 1
cur_len -= 1
if cur_len > max_len:max_len = cur_len
lookup.add(s[i])
return max_len
复杂度分析
令 n 为数组长度。
public int lengthOfLongestSubstring(String s) { if (s.length()==0) return 0; HashMap<Character, Integer> map = new HashMap<Character, Integer>(); int max=0; for (int i=0, j=0; i<s.length(); ++i){ if (map.containsKey(s.charAt(i))){ j = Math.max(j,map.get(s.charAt(i))+1); } map.put(s.charAt(i),i); max = Math.max(max,i-j+1); } return max; }
一般解法
``
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || "".equals(s)) {
return 0;
}
if ("".equals(s.trim())) {
return 1;
}
int max = 1;
char s0 = s.charAt(0);
StringBuffer validStr = new StringBuffer(s0+"");
for (int i = 1; i < s.length(); i++) {
//说明不存在
if (validStr.toString().indexOf(s.charAt(i)) == -1) {
validStr.append(s.charAt(i));
} else {
//如果存在重复
max = Math.max(max, validStr.toString().length());
int start = validStr.toString().indexOf(s.charAt(i));
validStr = new StringBuffer(validStr.toString().substring(start + 1));
validStr.append(s.charAt(i));
}
}
max = Math.max(max, validStr.toString().length());
return max;
}
}
时间复杂度:O(n)
空间复杂度:O(n)
哈希表+双指针
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.size() == 0) return 0;
unordered_map<char, int> hash;
int res = 0;
for (int i = 0, j = 0; i < s.size(); i ++) {
hash[s[i]] ++;
while (hash[s[i]] > 1) hash[s[j ++]] --;
res = max(res, i - j + 1);
}
return res;
}
};
补卡
hashmap + 2 pointers
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
res = 0
i = 0
hashmap = collections.defaultdict(int)
for j in range(len(s)):
curr = s[j]
if curr in hashmap and hashmap[curr] >= i:
i = hashmap[curr] + 1
res = max(res, j-i+1)
hashmap[curr] = j
return res
Time: O(n) Space: O(n)
双指针+集合判断是否之前出现过
如果左侧不再是起始位置,则需要移出之前左端点加入的元素。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_set<char> myset;
if(s.size()==0) return 0;
int ans = 0;
int right=-1, start=0;
for(;start<s.size();start++){
if(start!=0){
myset.erase(s[start-1]);
}
while(right+1<s.size() && !myset.count(s[right+1])){
myset.insert(s[right+1]);
right++;
}
ans = max(ans, right-start+1);
}
return ans;
}
};
Time:O(N^2) Space:O(1)
通过双指针和set检测是否有相同元素,有就左移set
Python3 Code:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left,right = 0,0
resMax = 0
hashSet = set()
# 通过双指针和set检测是否有相同元素,有就左移set
while right < len(s):
while s[right] in hashSet:
hashSet.remove(s[left])
left += 1
hashSet.add(s[right])
resMax = max(resMax, len(hashSet))
# print(hashSet)
right += 1
return resMax
复杂度分析
令 n 为数组长度。
class Solution: def lengthOfLongestSubstring(self, s: str) -> int: if s=='': return 0
cur=s[0]
hashmap=dict()
for j in s[1:]:
if j not in cur:
cur+=j
if j==s[-1]:
hashmap[cur]=len(cur)
print(hashmap[cur])
else:
hashmap[cur]=len(cur)
index=cur.index(j)
cur=cur[index+1:]+j
max1=1
for n in hashmap.values():
print(n)
if max1<n:
max1=n
return max1
暴力解比较好想,移动窗口来一步一步移动,如果有重复就把左指针移动到重复的后一位,确保不重复即可。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# brute force
if len(s) == 0: return 0 # make sure len(s) >= 2
i,j = 0,1
temp,max_len = s[i:j],1
for k in range(1,len(s)):
if s[k] in temp:
c = temp.find(s[k]) # 找到了在temp中 重复出现的那个位置,但是 不是在s的位置
i = i+c+1
temp = s[i:j+1]
max_len = max(max_len,len(temp))
j += 1
if j >= len(s): break
return max_len
time complexity: O(N**2) space complexity: O(N) 记录temp_string
利用一个hashmap, 记录每一个char 最近出现的index。 需要注意的一个点就是如果某个char出现但是并不在现在这个temp_string 中,就要把这个之前出现的char加进去,这个时候就可以用一个指针(类似left) 来记录起始点去跟hashmap 中该char 出现的index 对比。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) <= 1: return len(s)
d = {}
prev, max_len = -1,0
for i,c in enumerate(s):
if c not in d or d[c] < prev:
d[c] = i
max_len = max(i-prev,max_len)
else:
prev,d[c] = d[c],i
return max_len
time complexity: O(N)
space complexity: O(N)
补打卡:
滑动窗口,维持一个hash表。改模版越改越熟练啦哈哈
l, ans = 0,0 maps = defaultdict(int) for i in range(len(s)): maps[s[i]] += 1 while maps[s[i]] > 1: maps[s[l]] = maps.get(s[l],0)-1 l +=1 ans = max(ans,i - l + 1) return ans
遍历,都是O(N)
int lengthOfLongestSubString(string str) {
int res = 0;
int left = 0;
int right = 0;
unordered_map<char,int> dict;
while (right < str.size()) {
if (dict.find(str[right]) == dict.end())
dict[str[right]] = 1;
else
++dict[str[right]];
while (dict[str[right]] > 1) {
dict[str[left++]]--;
}
res = max(res, right - left + 1);
++right;
}
return res;
}```
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" 是一个子序列,不是子串。