hot100-子串

560. 和为k的子数组

560. 和为 K 的子数组 - 力扣(LeetCode)

python 复制代码
class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        # 求的是连续子串,所以排序不可以用
        # 又数字有正有负,所以快慢指针会失效!
        # 使用前缀和的思想,如果有一个子串j~i相加为k,则i的前缀和减去(j-1)的前缀和等于k
        d = {0:1}  # j=0,j-1=-1,我们定义一个0的前缀和
        pre = 0
        res = 0
        for i in range(len(nums)):
            pre += nums[i]  # i的前缀和
            res += d.get(pre-k,0)
            d[pre] = d.get(pre,0) + 1
        return res

时间复杂度:O(N)

空间复杂度:O(N)

239. 滑动窗口最大值

239. 滑动窗口最大值 - 力扣(LeetCode)

题目看起来很简单,但是我们如果在每个子数组中都去统计最大值,那么时间复杂度就会很高O(kN),最终会超时!

那么遍历数组的O(N)是不可少的,我们希望让获取max的操作变成O(1);假如我们仅仅是每遍历一个数组,仅仅记录最大值,但是我们就不知道这个最大值什么时候从当前窗口弹出!

最终实现使用的是单调队列!【这里单调队列更加适合,因为在滑动窗口的移动中,先进入的先弹出!】

python 复制代码
class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        res = []
        dq = []
        for i in range(k):
            # 单调队列:队首元素最大!
            # 其实我们不在乎队列里面到底存多少个元素,我们仅仅是留下较大的元素的下标
            # 如果新入队的元素下标和队首差距只要不超过k,那么当前的队首就还是最大元素
            # 如何保证单调性呢?从队尾开始比,比如7 3 5如果仅仅和队首比,就会有问题,中间那些小的依然在
            # 我们要保证的单调性就是队首到队尾的单调递减
            while dq and nums[i]>nums[dq[-1]]:
                dq.pop()  # 比的是队尾,弹的是队尾
            dq.append(i)
        res.append(nums[dq[0]])
        for i in range(k,len(nums)):
            while dq and nums[i]>nums[dq[-1]]:
                dq.pop()
            dq.append(i)
            while i-dq[0]>=k:
                dq.pop(0)  # 距离过大弹队首
            res.append(nums[dq[0]])
        return res
操作 Python list collections.deque 说明
append() 尾部入队 O(1) O(1) 两者都高效
pop() 尾部出队 O(1) O(1) 两者都高效
pop(0) 头部出队 O(n) O(1) 列表需要移动元素
insert(0, item) 头部入队 O(n) O(1) 列表需要移动元素
随机访问 queue[i] O(1) O(n) deque随机访问慢
python 复制代码
class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        res = []
        dq = collections.deque()
        for i in range(k):
            while dq and nums[i]>nums[dq[-1]]:
                dq.pop()  # 比的是队尾,弹的是队尾
            dq.append(i)
        res.append(nums[dq[0]])
        for i in range(k,len(nums)):
            while dq and nums[i]>nums[dq[-1]]:
                dq.pop()
            dq.append(i)
            while i-dq[0]>=k:
                dq.popleft()  # 距离过大弹队首
            res.append(nums[dq[0]])
        return res

但是如果是栈的话,用list差不多!【查看栈顶或者弹出栈顶,都是对列表最后一个元素操作,时间复杂度差不多!】

时间复杂度:O(N) 【每个元素除被遍历外,最多入对一次,出队一次 最多3N】

空间复杂度:O(k) 【队列的最大长度就是k】

76. 最小覆盖子串

76. 最小覆盖子串 - 力扣(LeetCode)

python 复制代码
class Solution(object):
    def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        m = len(s)
        n = len(t)
        if not s or not t or m<n:
            return ""
        dt = collections.Counter(t)
        ds = collections.Counter()
        min_len = m+1
        min_left = left = 0
        required = len(dt)
        cur = 0  # 记录一下有多少满足了
        for right in range(m):
            char = s[right]
            ds[char] += 1
            if char in dt and ds[char] == dt[char]:
                cur += 1
            # 既然找到了一个子串,我们其实可以尽可能的缩小左边界【注意,并非直接判断】
            # 比如最开始的几个字符可能都是其他字符,我们要while 缩小
            while left<=right and cur == required:
                win_len = right-left+1
                if win_len<min_len:
                    min_len = win_len
                    min_left = left
                left_char = s[left]
                ds[left_char] -= 1
                # 这里除了比较在不在,还需要比较大小,因为在之前的代码中,我们一旦满足某一个字符,但是之后可能会继续增加该字符
                if left_char in dt and ds[left_char] < dt[left_char]:
                    cur -=1
                left += 1
        return "" if min_len == m+1 else s[min_left:min_left+min_len]

时间复杂度:O(N) 最多相当于left和right两遍遍历!

空间复杂度:O(N) 两个字典

相关推荐
2301_822382762 小时前
开发一个简单的Python计算器
jvm·数据库·python
lambert.wang2 小时前
当使用 uv 下载 Python 解释器时出现异常,通常是因为网络连接问题导致无法从 GitHub 下载安装包
python·github·uv
2501_920999272 小时前
Django全栈开发入门:构建一个博客系统
jvm·数据库·python
ygklwyf2 小时前
无向图的连通性之割点/边,点/边双连通分量
算法·无向图·圆方树
2401_838472512 小时前
单元测试在C++项目中的实践
开发语言·c++·算法
码农阿豪2 小时前
影刀RPA与Java融合实践:打造高效智能的高铁票务解决方案
java·python·rpa
naruto_lnq2 小时前
移动语义与完美转发详解
开发语言·c++·算法
喵手2 小时前
Python爬虫实战:采集行业协会、研究机构等平台的政策文件列表与PDF链接批量收集系统,支持自动下载、分类归档和数据库管理(SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·sqlite持久化存储·采集行业协会、研究机构政策文件·pdf链接采集
MicroTech20252 小时前
自适生长的点云智能:MLGO微算法科技基于双阈值与DDM的仿生式配准算法
科技·算法