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%的用户

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

  • 相关阅读:
    JVM
    关于filter
    session
    xml
    互联网应用和企业级项目的区别
    本学期javaee目标
    团队项目软件度量
    团队项目总结
    团队项目来换网最新
    ubuntu18.04 编译opencv4.4.0 带cuda加速,ffmpeg
  • 原文地址:https://www.cnblogs.com/xiaoqiangink/p/12920383.html
Copyright © 2011-2022 走看看