【LeetCode】003——无重复字符的最长子串

题目描述

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

示例 1:

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

示例 2:

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

示例 3:

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

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

一、解法一

  • 1、先遍历整个字符串
  • 2、对遍历到的每次字符的后一个字符做判断(判断是否在遍历完的字符中出现过)
  • 3、建立一个空字符串,如果判断的字符没有出现过,则将它加入到建立的字符串中,并记录建立的字符串的长度
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        """
        :type s: str
        :rtype: int
        """
        maxLength = 0  # 记录最长字符串长度
        for i,_ in enumerate(s):  # enumerate生成字符串迭代器,下标以及对应的字符
            count = 0  # 记录字符串长度
            newChar = str()  # 新建字符串
            for j in s[i:]:  # 遍历外轮遍历字符的后面字符
                if j not in newChar:  # 如果没有出现
                    newChar += j  # 追加到新建的字符串中
                    count += 1  # 并且长度+1
                    if maxLength < count:  # 如果最大长度小于该长度
                        maxLength = count  # 更新最长长度
                else: # 如果出现过,退出本次内轮遍历      
                    break
        return maxLength

上面代码的算法复杂度为 O ( n 2 ) O(n^2) O(n2)

缺陷:

p w w k e w
i
    j
newChar = pw
=====================================
p w w k e w
  i
    j
newChar = w 
=====================================
p w w k e w
    i
    j
newChar = w 
  • 当内轮遍历的字符出现过,跳出内轮遍历,外轮遍历i加1,此时新建字符串少了个字符p,不可能比原本的长,因此我们可以直接跳到重复元素之后开始新的循环。
class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        start = maxLength = 0
        newChar = {}
        for index, char in enumerate(s):
            if char in newChar and start <= newChar[char]:  # 如果出现过,更新开始位置为重复元素之后的字符开始
                start = newChar[char] + 1
            else:  # 没有出现,更新最长长度
                maxLength = max(maxLength, index - start + 1)
            usedChar[char] = index
        return maxLength

时间复杂度是 O ( n ) O(n) O(n),空间复杂度也是 O ( n ) O(n) O(n)

二、解法二(滑动窗口)

建立一个256位大小的整型数组 freg,用来建立字符和其出现位置之间的映射。

维护一个滑动窗口,窗口内的都是没有重复的字符,去尽可能的扩大窗口的大小,窗口不停的向右滑动。

  • (1)如果当前遍历到的字符从未出现过,那么直接扩大右边界;
  • (2)如果当前遍历到的字符出现过,则缩小窗口(左边索引向右移动),然后继续观察当前遍历到的字符;
  • (3)重复(1)、(2),直到左边索引无法再移动;
  • (4)维护一个结果res,每次用出现过的窗口大小来更新结果res,最后返回res获取结果。

在这里插入图片描述

1、Java代码
public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int res = 0;
        int l = 0, r = 0;
        Set<Character> set = new HashSet<>();
        while(l < n && r < n){
           if(set.contains(s.charAt(r))){
               set.remove(s.charAt(l++));
           }else{
               set.add(s.charAt(r++));
               res = Math.max(res, r - l);
           }
        }
        return res;
    }
}
2、C++代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) 
    {
        int l = 0;
        int r = 0;
        int maxLength = 0;
        int usedChar[256] = { 0 };
        while (l < s.size())
        {
            if (r < s.size() && usedChar[s[r]] == 0)
            {
                usedChar[s[r++]] += 1;
            }
            else
            {
                usedChar[s[l++]] -= 1;
            }
            maxLength = max(maxLength, r - l);
        }
        return maxLength;
    }
};
3、Python代码
class Solution:
    """
    :type s: str
    :rtype: int
    """
    def lengthOfLongestSubstring(self, s):
        l = 0
        r = 0
        maxLength = 0
        s_len = len(s)
        usedChar = [0] * 256  # 通过符号表记录符号出现次数
        while l < s_len:
            if r < s_len and usedChar[ord(s[r])] == 0:
                usedChar[ord(s[r])] += 1
                r += 1
            else:
                usedChar[ord(s[l])] -= 1
                l += 1
            maxLength = max(maxLength, r - l)
        return maxLength
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值