[剑指Offer] 48_最长不包含重复字符的子字符串

67 篇文章 0 订阅
42 篇文章 0 订阅

题目

请从字符串中找到一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
假设该字符串只包含’a’~'z’的字符。

例:

在字符串’arabcacfr’中,最长的不包含重复字符的子字符串是"acfr",长度为4。


思路

  1. 遍历字符串,计算以每个字符为结尾的不含重复字符的子字符串的长度,更新最长长度。这里运用了动态规划解决公共子问题。不需要向前判断到头,只需要判断到上一个重复出现的地方即可,也就是以前一个位置为结尾的最长无重复子串是否加上本位置还是无重复的。还有一个关键在于,如何能最快的判断是否存在重复字符。如果每次都向前逐个比较,总复杂度是O(n^2)。为了能在O(1)内判断,我们用建立一个缓存列表,保存此前a~z字母最后出现的位置。如果出现重复,则从前一个出现的位置开始计算新的长度,否则+1即可。
    1. 时间复杂度:O(n),O(n)遍历,O(1)判断重复
    2. 空间复杂度:O(1),固定大小的辅助数组

代码

思路1: 时间复杂度:O(n),空间复杂度:O(1)

def longest_sub_str_without_dup(string):
    """
    :param string: string
    :return: max length of substr with out duplication
    """
    cur_len = 0 # the length of non-dup-substring ending with current position
    max_len = 0 # max length of non-dup-substring ending
    last_pos = [-1] * 26 # -1 = didn't appear
    for i in range(len(string)):
        curchr_pos_i = ord(string[i]) - ord('a') # a= 0 ~ z=25
        cur_chr_pre_i = last_pos[curchr_pos_i] # last appear position
        if i - cur_len > cur_chr_pre_i:
            cur_len += 1
        else:
            cur_len = i - cur_chr_pre_i
        max_len = max(max_len, cur_len) # refresh the max length
        last_pos[curchr_pos_i] = i
    return max_len

思考

同样的题目

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

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

示例 1:

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

示例 2:

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

示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

代码

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        from collections import OrderedDict
        l = len(s)
        sub = ''        
        submax = 0
        for i in range(l):
            if s[i] in sub:               
                sub = sub[sub.index(s[i]) + 1:] + s[i]                        
            else:                
                sub += s[i]                
                submax = max(submax, len(sub))           
        return submax

注意:
上面这段代码,是用的O(n)的查重方式,该题目中字符串中不仅包含’a’ - 'z’还有其他的字符。为了应用思路1的代码,只需要将辅助数组的大小扩展成全ASCII的大小即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值