LeetCode热题100---day 1(滑动窗口)

第一题 无重复字符的最长子串:

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

示例:

        输入:s = "abcabcbb"

        输出:3

        解释:因为无重复字符的最长子串是"abc",所以长度为3

问题分析:

        本题可以采用滑动窗口的思想,利用优先队列来充当滑动窗口。窗口初始化大小为0,在遇到窗口中不存在的字符,则窗口大小加一,并将该字符加入窗口(队列);若是该字符窗口中已经存在,则从队列头开始将字符依次弹出,直到窗口中没有该字符,最后将该字符加入窗口。遍历整个字符串。

代码实现:

        

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        # 滑动窗口算法
        windows = []
        length = 0
        for i in range(len(s)):
            while s[i] in windows:
                windows.pop(0)
            windows.append(s[i])
            if len(windows) > length:
                length += 1
        
        return length

第二题 找到字符串中所有字母异位词:

        给定两个字符串s和p,找到s中所有p的异位词的子串,返回这些字串的起始索引。不考虑答案输出的顺序。

示例:

        输入:s = "cbaebabacd", p = "abc"

        输出:[0, 6]

        解释:起始索引为0的子串是"cba", 它是“abc“的异位词

                   起始索引为6的子串是"bac",它也是“abc”的异位词

问题分析:

        首先考虑暴力解法,将p进行排序,再根据p的大小创建匹配窗口,从s的第1位一直匹配到s的第s_len - p_len + 1位,将每次窗口中的子串取出并进行排序后与排序后的p进行比较即可。

代码实现:

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        p_sorted = sorted(p)
        length = len(p)
        index = []
        i = 0
        while i < len(s):
            string = sorted(s[i:i+length])
            if string == p_sorted:
                index.append(i)
            i += 1
        return index
            

优化分析:

        暴力解法虽然能够求出最后答案,但是时间复杂度为O(n^2*logn),运行效率太慢。为此,我们对其进行进一步的优化。在暴力算法中,由于我们每次都应用了快排来找出异位词,快排的时间复杂度为O(n*logn),带来了大量的时间消耗。在优化算法中,我们采用记录每个字母的个数来比较异位词,这样就避免了使用开排算法。时间复杂度为O(n)。

代码实现:

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        # 计算字符串s和p的长度
        s_len, p_len = len(s), len(p)

        # 若s的长度小于p,则直接返回空
        if s_len < p_len:
            return []
        
        ans = []

        # 定义数字来维护当前窗口中各个字母的数字
        s_count = [0] * 26
        p_count = [0] * 26
        for i in range(p_len):
            s_count[ord(s[i]) - 97] += 1
            p_count[ord(p[i]) - 97] += 1
        
        if s_count == p_count:
            ans.append(0)

        for i in range(s_len - p_len):
            s_count[ord(s[i]) - 97] -= 1
            s_count[ord(s[i + p_len]) - 97] += 1

            if s_count == p_count:
                ans.append(i + 1)

        return ans
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值