zoukankan      html  css  js  c++  java
  • LeetCode 3. 无重复字符的最长子串

    题目:


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

    示例 1:

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

    示例 2:

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

    示例 3:

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

    思路:

    无重复,最长子串。首先想到的是遍历字串比较,不存在相同key, length长度就+1,如果存在则移位,从下一位开始继续比较。

    方法一:

    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
            length = upper = lower = 0  #长度变数初始赋值
            while upper < len(s): 
                if s[upper] not in s[lower:upper]: #依次遍历字串单个字节内容,是否在字串范围中
                    upper +=1 #不在,下限+1,往下位继续遍历
                    length = max(length,len(s[lower:upper])) #获得当前已遍历出的子串的最大长度
                else:
                    lower +=1 #当字串范围包含字节时,上限+1,跳过该位,往下位开始重新遍历
            return length
    

    执行用时 :84 ms, 在所有 Python 提交中击败了39.60%的用户

    内存消耗 :12.8 MB, 在所有 Python 提交中击败了15.15%的用户

    看起来这是笨方法,虽然我不懂算法最优解计算逻辑,但是明显感觉到这个方法每次都会从头开始遍历,有点浪费时间。

    方法二:

    思路:

    方法一是通过字符串的index 来移位,那我可不可以通过array来做类似的事情呢?当然可以

    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
            tmp=[]
            cur_len= max_len =0
            if len(s)==0:return 0
            for i in range(len(s)):
                if s[i] in tmp:
                    j=tmp.index(s[i])#求相同字符s[i]在tmp中的index
                    tmp=tmp[j+1:] #移位,将list更新为最新的子字符串
                    cur_len-=j   #更新子字符串长度 
                else:
                    cur_len+=1
                tmp.append(s[i])
                max_len=max(cur_len,max_len)
            return max_len
    

    执行用时 :76 ms, 在所有 Python 提交中击败了46.05%的用户

    内存消耗 :13.6 MB, 在所有 Python 提交中击败了6.06%的用户

    方法三:

    怎么才能节省时间呢?

    方法一用了str,方法二用了array,那么用dic 会怎样?
    思路:下面的方式通过dic 标记相同元素位置,相同元素出现前获取当前片段最大长度,出现相同元素时,理解成区间截取,截取出现相同元素index之前的区间部分肯定没有上一次的长度长,这部分可以舍弃,所以只需要记录出现相同元素后的index 位置在继续遍历,最后取长度最大值即可。

    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
             # 可抛弃字符串的索引尾值 - 字符串索引值,该索引值以及之前的字符都属于重复字符串中的一部分,不再在计算中涉及
            ignore_str_index_end = -1
            dic = {}        # 任意字符最后出现在索引的位置 - {字符: 字符索引值}
            max_length = 0  # 最长字符串长度
    
            for i, c in enumerate(s):
                # 如果字典中已经存在字符c,则字符c重复
                # 如果字符索引值大于ignore_str_index_end,则字符c在需处理的范围内(补充说明请参考备注一)            
                if c in dic and dic[c] > ignore_str_index_end:
                    # 先更新可抛弃字符串的索引尾值为字符c上一次的索引值
                    ignore_str_index_end = dic[c]
                    # 再更新字符c的索引值
                    dic[c] = i
                # 否则,
                else:
                    # 更新字符最近的索引位置
                    dic[c] = i
                    # 更新最大长度
                    max_length = max(i - ignore_str_index_end, max_length)
    
            return max_length
    

    执行用时 :72 ms, 在所有 Python 提交中击败了49.95%的用户

    内存消耗 :13 MB, 在所有 Python 提交中击败了6.06%的用户

    时间方面还是很长,放弃~。~重在理解算法思路。

  • 相关阅读:
    BZOJ 3205 [Apio2013]机器人 ——斯坦纳树
    BZOJ 3782 上学路线 ——动态规划 Lucas定理 中国剩余定理
    HDU 1423 Greatest Common Increasing Subsequence ——动态规划
    BZOJ 3309 DZY Loves Math ——莫比乌斯反演
    POJ 1038 Bugs Integrated, Inc. ——状压DP
    POJ 3693 Maximum repetition substring ——后缀数组
    POJ 2699 The Maximum Number of Strong Kings ——网络流
    POJ 2396 Budget ——有上下界的网络流
    BZOJ 4650 [Noi2016]优秀的拆分 ——后缀数组
    源码安装python
  • 原文地址:https://www.cnblogs.com/xiaoqiangink/p/12920383.html
Copyright © 2011-2022 走看看