leetcode-pp / 91alg-5-daily-check

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 22 】2021-10-01 - 3. 无重复字符的最长子串 #37

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

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" 是一个子序列,不是子串。

ZJP1483469269 commented 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)

ZiyangZ commented 2 years ago
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;
    }
}
sxr000511 commented 2 years ago

题目地址(3. 无重复字符的最长子串)

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?

  1. 窗口的长度是right - left +1

  2. 移动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 为数组长度。

minuet-red commented 2 years ago
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;
    }
};
AgathaWang commented 2 years ago

滑动窗口 + 双指针

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) 快慢指针各遍历一次
a244629128 commented 2 years ago

/**
 * @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)
lilixikun commented 2 years ago

思路

哈希表 + 滑动窗口

user1689 commented 2 years ago

题目

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

思路

哈希表+滑动窗口,哈希集合+滑动窗口

python

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

复杂度分析

相关题目

  1. https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/hua-dong-chuang-kou-by-powcai/
  2. https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/yi-ge-mo-ban-miao-sha-10dao-zhong-deng-n-sb0x/
ghost commented 2 years ago

题目

  1. Longest Substring Without Repeating Characters

思路

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)

yan0327 commented 2 years ago

本质就是滑动窗口加哈希表,哈希表用于统计该字符是否出现过。 当发现有字符之前出现过,则将左指针的哈希值去掉,然后右移左指针。 最终找到一个最长子串

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)

xbhog commented 2 years ago

3. 无重复字符的最长子串

思路:

遍历字符串,一个指针先存到map中,保存值和下标,遍历的时候如果存在,那么更新J值,map保存当前元素,

res与i-j+1取最大值即可;

Java代码段:

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)

lxy030988 commented 2 years ago

思路

代码 js

/**
 * @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
}

复杂度分析

wangyifan2018 commented 2 years ago

滑动窗口+哈希表

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
}
HouHao1998 commented 2 years ago

思想

哈希表,遍历整个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)

chakochako commented 2 years ago
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
pan-qin commented 2 years ago

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;
    }
}
biscuit279 commented 2 years ago

思路:哈希表+滑动窗口

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)

biancaone commented 2 years ago

思路 🏷️

哈希表+双指针

代码 📜

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
Francis-xsc commented 2 years ago

思路

双指针+哈希表

代码


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;
    }
};

复杂度分析

chun1hao commented 2 years ago
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;
};
laurallalala commented 2 years ago

代码

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)

复杂度

liuyangqiQAQ commented 2 years ago

hash表

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表存储的字符长度。

last-Battle commented 2 years ago

思路

关键点

代码

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 为数组长度。

Wu-zonglin commented 2 years ago

思路

滑动窗口

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

复杂度分析

L-SUI commented 2 years ago

/**

jiabin123 commented 2 years ago

思路: 双指针

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

Complexity

hewenyi666 commented 2 years ago

题目名称

3. 无重复字符的最长子串

题目链接

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

复杂度分析

Huangxuang commented 2 years ago

题目:3. Longest Substring Without Repeating Characters

思路

代码

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;
    }
}

复杂度分析

xixvtt commented 2 years ago
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)

Tao-Mao commented 2 years ago

Idea

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.

Code

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;
    }
}

Complexity

ergwang commented 2 years ago

思路

  1. 首先想到滑动窗口解决,利用双指针操作
  2. 看到标签提示用hashMap,然后就写成了这个“四不像”,思想还是滑动窗口的思想
  3. 又费时间又费空间

代码

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

iceburgs commented 2 years ago

题目名称

  1. 无重复字符的最长子串

题目链接 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)

Socrates2001 commented 2 years ago

C implementation

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;    
}
mokrs commented 2 years ago

思路:

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);
}

复杂度:

qibao1112 commented 2 years ago

思路

滑动窗口+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)

JiangyanLiNEU commented 2 years ago
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
babbomax98 commented 2 years ago

思路

使用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)
chen445 commented 2 years ago

思路

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 

复杂度

Solution 1

Time:O(n)

Space:O(n)

Solution 2

Time: O(n)

Space: O(n)

ai2095 commented 2 years ago

LC3. Longest Substring Without Repeating Characters

https://leetcode.com/problems/longest-substring-without-repeating-characters

Topics

Similar Questions

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.

代码 Python

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)

zhiyuanpeng commented 2 years ago

··· 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)·

leolisgit commented 2 years ago

思路

  1. 因为是求最长的substring,很容易想到滑动窗口,并且窗口收缩的条件就是出现了重复元素。
  2. 因为元素不能重复,所以使用HashSet来记录窗口内的元素。
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)

watermelonDrip commented 2 years ago
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)

peteruixi commented 2 years ago

思路

输入: 一个字符串 输出: 字符串中, 最长不包含重复字符字串的长度

  1. 利用双指针编程思想去截取子串
  2. 利用HashMap来判断字串是否包含重复字符

    代码

    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;
    }

    复杂度分析

    • 时间复杂度 O(N)
    • 空间复杂度 O(N)
muimi commented 2 years ago

思路

维护一个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;
  }
}

复杂度

TimmmYang commented 2 years ago

思路

哈希+滑动窗口。

代码

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)

Dana-Dai commented 2 years ago
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; 
    }
};
kennyxcao commented 2 years ago

3. Longest Substring Without Repeating Characters

Intuition

Code

/**
 * @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;
};

Complexity Analysis

JK1452470209 commented 2 years ago

思路

暴力循环,对字符串进行扫描,用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中字符集的个数

shamworld commented 2 years ago

思路

哈希

代码

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;

复杂度分析

juleijs commented 2 years ago

思路

滑动窗口

代码

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;
}

复杂度