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

OASans commented 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
Auto-SK commented 2 years ago

思路

利用集合的不重复性,移动窗口,将重复的元素移除,记录遍历过程窗口的最大长度。

程序

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

复杂度

yj9676 commented 2 years ago

[TOC]

LC3 无重复字符的最长子串 [Medium]

Longest Substring Without Repeating Characters

Solution

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

复杂度分析

baoqin87 commented 2 years ago

思路

/**
 * @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
};
ChenJingjing85 commented 2 years ago

思路

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

复杂度分析

JAYWX commented 2 years ago
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
machuangmr commented 2 years ago

思路

15691894985 commented 2 years ago

【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

复杂度分析:

jaysonss commented 2 years ago
joriscai commented 2 years ago

思路

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

复杂度分析

MissNanLan commented 2 years ago

思路

代码

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

flame0409 commented 2 years ago

思路 定义一个 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)

HackBL commented 2 years ago

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

linrAx commented 2 years ago

思路

滑动窗口

代码

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)

JinhMa commented 2 years ago

class Solution { public int lengthOfLongestSubstring(String s) { int l = s.length(); int start = 0; int right = 0; HashSet record = new HashSet<>(); int ans = 0; while(start<l){ while(right<l && record.add(s.charAt(right))){ right++; } ans = Math.max(ans, right-start); while(right<l && record.contains(s.charAt(right))){ record.remove(s.charAt(start)); start++; } if(right==l){ break; } } return ans; } }

ZhuMengCheng commented 2 years ago

思路: 利用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)
HydenLiu commented 2 years ago

js

/**
 * @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
};
CruiseYuGH commented 2 years ago

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)

itsjacob commented 2 years ago

Intuition

Implementation

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

Complexity

JianXinyu commented 2 years ago

思路

Sliding window 通常用于数组和字符串,移动一个端点,快速地确定另一个端点

logic:

  1. use HashSet to store the sliding window $[i, j]$ characters. initially, $i==j$
  2. slide the index $j$ to the right
    • if $str[j]$ isn't in the HashSet, slide $j$ further. Repeat this.
    • if $str[j] == str[i'],i'\in[i,j)$ , make $i=i'+1$

      Code

      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)

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

解法一

弄一个集合,集合中如何出现重复元素,从左向右删除字符,直到集合不重复为止

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)

qixuan-code commented 2 years ago

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

复杂度分析

naivecoder-irl commented 2 years ago

思路

参考:https://leetcode-solution-leetcode-pp.gitbook.io/leetcode-solution/medium/3.longest-substring-without-repeating-characters

利用哈希表+滑动窗口;

用双指针定义一个滑动窗口,右指针指向的字符不在窗口中重复时,右指针进一步;遇到重复字符,左指针收缩到字符上次出现的位置。 使用哈希表记录每一个字符出现的最新位置 使用单独一个变量存储窗口的最大长度

代码

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

复杂度分析

ZETAVI commented 2 years ago

思路

语言

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

复杂度分析

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

思路

哈希表+滑动窗口

代码

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

复杂度分析

moxiaopao278 commented 2 years ago

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

}

Forschers commented 2 years ago
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;
}
bolunzhang2021 commented 2 years ago
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)。

lihanchenyuhua commented 2 years ago

class Solution { public: int lengthOfLongestSubstring(string s) { // 哈希集合,记录每个字符是否出现过 unordered_set occ; int n = s.size(); // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动 int rk = -1, ans = 0; // 枚举左指针的位置,初始值隐性地表示为 -1 for (int i = 0; i < n; ++i) { if (i != 0) { // 左指针向右移动一格,移除一个字符 occ.erase(s[i - 1]); } while (rk + 1 < n && !occ.count(s[rk + 1])) { // 不断地移动右指针 occ.insert(s[rk + 1]); ++rk; } // 第 i 到 rk 个字符是一个极长的无重复字符子串 ans = max(ans, rk - i + 1); } return ans; } };

Zhang6260 commented 2 years ago

JAVA版本

思路:使用滑动窗口,判断当前字符串不在滑动窗口中的话,就移动右指针,如果在的话,就移动左指针,直到将滑动窗口中不含有当前的字符。记录滑动窗口最大时候的字串。

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

时间复杂度:O(n)

空间复杂度:O(n)

flagyk5 commented 2 years ago
滑动窗口,双指针+字典
时间: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
vaqua commented 2 years ago

思路

哈希表+滑动窗口

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

zhangyalei1026 commented 2 years ago

思路

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)

septasset commented 2 years ago

思考

关键点

代码(Python)

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

复杂度分析

xuezhongyuan commented 2 years ago

代码:

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

暴力解法:

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

jerry9926 commented 2 years ago

思路

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

复杂度分析

ruohai0925 commented 2 years ago

题目地址()

题目描述

前置知识

公司

思路

关键点

代码

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

yuxiangdev commented 2 years ago

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

ymkymk commented 2 years ago

思路

一般解法

代码

``

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)

doMoreCode commented 2 years ago

思路

哈希表+双指针

code

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

补卡

思路

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)

V-Enzo commented 2 years ago

思路

双指针+集合判断是否之前出现过

  1. 遍历所有左侧位置,不断移动右侧指针,判断右指针指向的元素之前是否出现过。(只是在实现的时候用了right=-1,所以写代码的时候要判断right+1)
  2. 如果之前出现过,则记录下最长长度,随后右移指针。
  3. 如果左侧不再是起始位置,则需要移出之前左端点加入的元素。

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

    Complexity:

    Time:O(N^2) Space:O(1)

freesan44 commented 2 years ago

思路

通过双指针和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 为数组长度。

ymwang-2020 commented 2 years ago

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

暴力解比较好想,移动窗口来一步一步移动,如果有重复就把左指针移动到重复的后一位,确保不重复即可。

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)

Leonalhq commented 2 years ago

补打卡:

思路

滑动窗口,维持一个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)

hellowxwworld commented 2 years ago

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