LeetCode-03 无重复字符的最长子串(Longest Substring Without Repeating Characters)

题目描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例

示例  1:

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是  "wke",所以其长度为 3。

请注意,你的答案必须是 子串 的长度,"pwke"  是一个子序列,不是子串。

分析

我们可以维护一个范围[i, j)的窗口来保存子串,使用 HashSet/HashMap 作为容器,对 s 进行遍历。如果窗口中不包含有 s[j],则将 s[j]添加到窗口中并计数,反之,将 s[i]从窗口中移除。也可以使用一个 int 数组来代替 HashSet。

数组 说明
int [26] 'A'-'Z'和'a'-'z'
int [128] ASCII 码
int [256] ASCII 扩展码

时间复杂度为 O(n),遍历一次 s,n 为 s 的长度;
空间复杂度为 O(min(m,n)),需要额外的 HashSet,取决于 s 的长度 n 和窗口长度 m。

实现

C#

class Solution
{
    public int LongestSubstringWithoutRepeating(string s)
    {
        // 96 ms int[]
        // int n = s.Length, ans = 0;
        // int[] index = new int[128]; // new int[256];
        // for (int j = 0, i = 0; j < n; j++)
        // {
        //     i = Math.Max(index[s[j]], i);
        //     ans = Math.Max(ans, j - i + 1);
        //     index[s[j]] = j + 1;
        // }
        // return ans;

        // 100 ms HashSet<char>
        // int len = s.Length;
        // HashSet<char> set = new HashSet<char>();
        // int ans = 0, i = 0, j = 0;
        // while (i < len && j < len)
        // {
        //     if (!set.Contains(s[j]))
        //     {
        //         set.Add(s[j++]);
        //         ans = Math.Max(ans, j - i);
        //     }
        //     else set.Remove(s[i++]);
        // }
        // return ans;

        // 100ms Dictionary<char, int>
        int n = s.Length, ans = 0;
        Dictionary<char, int> dic = new Dictionary<char, int>();
        for (int j = 0, i = 0; j < n; j++)
        {
            if (dic.ContainsKey(s[j]))
            {
                i = Math.Max(dic[s[j]], i);
                dic[s[j]] = j + 1;
            }
            else dic.Add(s[j], j + 1);
            ans = Math.Max(ans, j - i + 1);
        }
        return ans;
    }
}

C++

class Solution {
public:
    int lengthOfLongestSubstring(std::string s) {
        std::vector<int> dic(256, -1);
        int maxlen = 0, start = -1;
        int len = s.length();
        for (int i = 0; i != len; i++) {
            if (dic[s[i]] > start)
                start = dic[s[i]];
            dic[s[i]] = i;
            maxlen = std::max(maxlen, i - start);
        }
        return maxlen;
    }
}

Python

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        size = len(s)
        ans = i = 0
        index = [0] * 128
        for j in range(0, size):
            i = max(index[ord(s[j])], i)
            ans = max(ans, j - i + 1)
            index[ord(s[j])] = j + 1
        return ans

Rust

pub fn length_of_longest_substring(s: String) -> i32 {
    let (mut n, mut res) = (s.len(), 0);
    // let mut map = HashMap::<u8, i32>::new();
    // let mut i = 0;
    // let chars = s.as_bytes();
    // for j in 0..n {
    //     if map.contains_key(&chars[j]) {
    //         i = max(*map.get(&chars[j]).unwrap(), i);
    //         map.entry(chars[j]).and_modify(|e| *e = j as i32 + 1);
    //     } else {
    //         map.insert(chars[j], (j + 1) as i32);
    //     }
    //     res = max(res, j as i32 - i + 1);
    // }

    let mut map = vec![0; 128];
    let chars = s.as_bytes();
    let mut i = 0;
    for j in 0..n {
        i = max(map[chars[j] as usize], i);
        res = max(res, j as i32 - i + 1);
        map[chars[j] as usize] = j as i32 + 1;
    }
    res
}

Typescript

function lengthOfLongestSubstring(s: string): number {
  let len: number = s.length,
    ans: number = 0;
  let index: Array<number> = new Array<number>(128).fill(0);
  for (let i = 0, j = 0; j < len; j++) {
    i = Math.max(index[s[j].charCodeAt(0)], i);
    ans = Math.max(ans, j - i + 1);
    index[s[j].charCodeAt(0)] = j + 1;
  }
  return ans;
}

C

int lengthOfLongestSubstring(char * s){
      int len = 0;
      char *end = s, *temp;
      char *addressTable[128] = {NULL};
      while (*end) {
        temp = addressTable[*end];
        addressTable[*end] = end;
        if (temp >= s) {
          len = end - s > len ? end - s : len;
          s = temp + 1;
        }
        end++;
      }
      len = end - s > len ? end - s : len;
      return len;
}
posted @ 2021-11-25 19:08  trickyrat  阅读(46)  评论(0)    收藏  举报