HOT 100 | 【子串】76.最小覆盖子串、【普通数组】53.最大子数组和、【普通数组】56.合并区间

一、【子串】76.最小覆盖子串

1. 解题思路

        定义两个哈希表分别用于 t 统计字符串 t 的字符个数,另一个sub_s用于统计字符串 t 在 s 的子串里面字符出现的频率。

        为了降低时间复杂度,定义一个变量t_count用于统计 t 哈希表中元素的个数。哈希表sub_s是一边遍历字符串s一边构建的,所以定义一个变量have用于统计有几个元素满足了t哈希表的条件。当且仅当t_count == have,则表明子串sub_s是涵盖t中所有字符。

        暴力枚举所有s的子串,然后在满足条件的子串中选出长度最小的返回即可,但是这种方法时间复杂度为O(n^2),我们可以选择时间复杂度更优的滑动窗口来解决(时间复杂度O(n))。

        (1)从s开始进行遍历,如果该字符在t中存在,那么更新sub_s和have后,若没有满足条件t_count == have,那么则移动滑动窗口的右边界;如果该字符在t中不存在,那么窗口右边界直接继续向右移动。

        (2)直到满足条件t_count == have,则记录当前窗口的长度length和起点start,然后将窗口的左边界向右移动后,更新sub_s和have。

        (3)如果sub_s和have不满足t_count == have,则重复步骤(1)。

        (4)如果再次遇到满足条件的子串,则判断其长度是否小于length,如果是则更新length和start。

2. 代码实现

class Solution:
    def minWindow(self, s:str, t:str)->str:
        ans_left = -1
        ans_right = len(s)
        cnt_s = Counter()
        cnt_t = Counter(t)
        
        left = 0
        for right, c in enumerate(s):
            cnt_s[c] += 1
            while cnt_s >= cnt_t:
                if right-left < ans_right-ans_left:
                    ans_left, ans_right = left, right 
                cnt_s[s[left]] -= 1
                left += 1
        return "" if ans_left < 0 else s[ans_left:ans_right+1]
                    

二、【普通数组】53.最大子数组和

1. 解题思路

        本题采用动态规划五部曲进行解答。

        (1)定义dp数组:dp[i]表示的是以nums[i]结尾的最大连续子序列的和。

        (2)递推公式:可以发现,连续子序列的和dp[i]分为两种状态可以得到,一是dp[i-1]+nums[i],也就是延续前面的子序列;另一种是nums[i],也就是从该元素开始的子序列。因此,得到递推公式:dp = max(dp[i-1]+nums[i], nums[i] )

        (3)初始化:dp[0]必须初始化为数组的头元素,即dp[0] = nums[0],其余的元素可以初始化任意值,因为随着状态转移其真正的值会覆盖初始值。

        (4)遍历顺序:正常的遍历顺序即可。

        (5)打印:注意最后输出的不是dp[i],因为最大子数组和不一定是最后一个元素结尾的。

2. 代码实现

class Solution:
    def maxSubArray(self, nums: List[int])->int:
        dp = [0] * len(nums)
        dp[0] = nums[0]
        for i in range(1, len(nums)):
            dp[i] = max(dp[i-1]+nums[i], nums[i])
        return max(dp)

三、【普通数组】56.合并区间

1. 解题思路

        本题采用贪心算法

        (1)为了方便对区间进行合并,需要对区间按照左边界或者右边界进行排序

        (2)判断区间是否发生重叠:当前区间的左边界是否小于等于上一个区间的右边界,如果是则说明这两个区间发生了重叠,那么需要合并区间;如果不是则说明没有发生重叠,那么定义一个新数组存放将当前区间。

        (3)注意:在合并区间的过程中,是更新区间的右边界,但最新的右边界并不一定是当前区间的右边界,因为可能存在上一个区间右边界大于当前区间右边界的情况,所以在进行合并的时候,更新右边界应该是取当前区间右边界和上一个区间右边界的最大值

2. 代码实现

class Solution:
    def merge(self, intervals:List[List[int]])->List[List[int]]:

        # 定义一个变量result用于存放结果集
        result = []

        # 判断给出的intervals是否为空
        if len(intervals) == 0:
            return result

        # 按照左边界对区间进行排序
        intervals.sort(key = lambda x: x[0])
        
        # 将第一个区间加入到结果集中,再进行更新即可
        result.append(intervals[0])

        # 遍历区间,从1开始是因为为了防止i-1异常
        for i in range(1, len(intervals)):
            # 判断区间是否重叠
            if result[-1][1]>=intervals[i][0]:
                result[-1][1] = max(result[-1][1], intervals[i][1])
            else:
                result.append(intervals[i])
        return result

# 力扣hot100刷题记录表 ### 一,哈希部分 - [ ] 1. 两数之 (简单) - [ ] 2. 字母异位词分组(中等) - [ ] 3. 最长连续序列(中等) ### 二,双指针部分 - [ ] 4. 移动零(简单) - [ ] 5. 盛水最多的容器 (中等) - [ ] 6. 三数之 (中等) - [ ] 7. 接雨水(困难) ### 三,滑动窗口 - [ ] 8. 无重复字符的最长子串(中等) - [ ] 9. 找到字符中所有的字母异位词(中等) ### 四,子串 - [ ] 10. 为k的子数组(中等) - [ ] 11. 滑动窗口最大值(困难) - [ ] 12. 最小覆盖子窜(困难) ### 五,普通数组 - [ ] 13. 最大子数组(中等) - [ ] 14. 合并区间(中等) - [ ] 15. 轮转数组(中等) - [ ] 16. 除自身以外数组的乘积(中等) - [ ] 17. 缺失的第一个正数(困难) ### 六,矩阵 - [ ] 18. 矩阵置零(中等) - [ ] 19. 螺旋矩阵 (中等) - [ ] 20. 旋转图像 (中等) - [ ] 21. 搜索二维矩阵Ⅱ (中等) ### 七,链表 - [ ] 22. 相交链表 (简单) - [ ] 23. 反转链表 (简单) - [ ] 24. 回文链表 (简单) - [ ] 25. 环形链表 (简单) - [ ] 26. 环形链表Ⅱ (中等) - [ ] 27. 合并两个有序链表 (简单) - [ ] 28. 两数相加 (中等) - [ ] 29. 删除链表的倒数第 N 个结点 (中等) - [ ] 30. 两两交换链表中的节点 (中等) - [ ] 31. K个一组翻转链表 (困难) - [ ] 32. 随机链表的复制 (中等) - [ ] 33. 排序链表 (中等) - [ ] 34. 合并 K 个升序链表 (困难) - [ ] 35. LRU 缓存 (中等) ### 八,二叉树 - [ ] 36. 二叉树的中序遍历 (简单) - [ ] 37. 二叉树的最大深度 (简单) - [ ] 38. 翻转二叉树 (简单) - [ ] 39. 对称二叉树 (简单) - [ ] 40. 二叉树的直径 (简单) - [ ] 41. 二叉树的层序遍历 (中等) - [ ] 42. 将有序数组转换为二叉搜索树 (简单) - [ ] 43. 验证二叉搜索树 (中等) - [ ] 44. 二叉搜索树中第 K 小的元素 (中等) - [ ] 45. 二叉树的右视图 (中等) - [ ] 46. 二叉树展开为链表 (中等) - [ ] 47. 从前序与中序遍历序列构造二叉树 (中等) - [ ] 48. 路径总 III (中等) - [ ] 49. 二叉树的最近公共祖先 (中等) - [ ] 50. 二叉树中的最大路径 (困难) ### 九,图论 - [ ] 51. 岛屿数量 (中等) - [ ] 52. 腐烂的橘子 (中等) - [ ] 53. 课程表 (中等) - [ ] 54. 实现 Trie(前缀树) (中等) ### 十,回溯 - [ ] 55.全排列(中等) - [ ] 56.子集(中等) - [ ] 57.电话号码的字母组合(中等) - [ ] 58.组合总(中等) - [ ] 59.括号生成(中等) - [ ] 60.单词搜索(中等) - [ ] 61.分割回文串(中等) - [ ] 62.N 皇后 (困难) ### 十一,二分查找 - [ ] 63. 搜索插入位置 (简单) - [ ] 64. 搜索二维矩阵 (中等) - [ ] 65. 在排序数组中查找元素的第一个最后一个位置 (中等) - [ ] 66. 搜索旋转排序数组 (中等) - [ ] 67. 寻找旋转排序数组中的最小值 (中等) - [ ] 68. 寻找两个正序数组的中位数 (困难) ### 十二,栈 - [ ] 69. 有效的括号 (简单) - [ ] 70. 最小栈 (中等) - [ ] 71. 字符串解码 (中等) - [ ] 72. 每日温度 (中等) - [ ] 73. 柱状图中最大的矩形 (困难) ### 十三,堆 - [ ] 74. 数组中的第K个最大元素 (中等) - [ ] 75. 前K 个高频元素 (中等) - [ ] 76. 数据流的中位数 (闲难) ### 十四,贪心算法 - [ ] 77. 买卖股票的最佳时机 (简单) - [ ] 78. 跳跃游戏 (中等) - [ ] 79. 跳跃游戏 III (中等) - [ ] 80. 划分字母区间 (中等) ### 十五,动态规划 - [ ] 81. 爬楼梯(简单) - [ ] 82. 杨辉三角 (简单) - [ ] 83. 打家劫舍 (中等) - [ ] 84. 完全平方数 (中等) - [ ] 85. 零钱兑换 (中等) - [ ] 86. 单词拆分 (中等) - [ ] 87. 最长递增子序列 (中等) - [ ] 88. 乘积最大子数组 (中等) ### 十六,多维动态规划 - [ ] 91. 不同路径 (中等) - [ ] 92. 最小路径 (中等) - [ ] 93. 最长回文子串 (中等) - [ ] 94. 最长公共子序列 (中等) - [ ] 95. 编辑距离 (中等) ### 十七,技巧 - [ ] 96. 只出现一次的数字 (简单) - [ ] 97. 多数元素 (简单) - [ ] 98. 颜色分类 (中等) - [ ] 99. 下一个排列 (中等) - [ ] 100. 寻找重复数 (中等) 如何使用
07-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值