前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Leetcode 【485、1004、1052】

Leetcode 【485、1004、1052】

作者头像
echobingo
发布于 2019-06-18 10:49:45
发布于 2019-06-18 10:49:45
72400
代码可运行
举报
运行总次数:0
代码可运行
问题描述:【Array】485. Max Consecutive Ones
解题思路:

因为要找最长连续 1 子数组的长度,所以我们只需要遍历一次,记录每段连续 1 的长度;如果遇到 0,就更新当前最大长度,然后当前长度清零,继续向后遍历。时间复杂度为 O(n)。

Python3 实现:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        max_ = tem = 0
        for i in range(len(nums)):
            if nums[i] == 0:
                max_ = max(max_, tem)  # 更新当前最大长度
                tem = 0
            else:
                tem += 1
        return max(max_, tem)
问题描述:【Array】487. Max Consecutive Ones

收费暂时做不了 hhh~ 题目是最多改变其中 1 个 0 变成 1,然后求最长连续 1 子数组的长度。可以采用滑动窗口的做法,在下面的 1004 题有具体的解法,代码和 1004 完全一样。

问题描述:【Sliding Window】1004. Max Consecutive Ones III
解题思路:

这道题是最多改变 K 个 1 变成 0,然后求最长连续 1 子数组的长度。很容易想到滑动窗口的思路(487 做法和本题做法一致,只不过 487 中 K = 1):

我们来定义本题的滑动窗口:因为肯定将所有 K 个 0 改成 1 才能获得最大长度,因此滑动窗口中记录包含 K 个 0 之后的最长连续 1 子数组。注意到这个滑动窗口的大小是不固定的,因此,我们在滑动的过程中,要记录滑动窗口的起始位置(终止位置不用记,因为终止位置就是当前遍历的位置)。

如何更新滑动窗口呢?如果我们的滑动窗口中已经有 K 个 0 了,后面又遇到一个 0,那么我们就要移动滑动窗口,根据滑动窗口的起始位置找到窗口中最前面的 0,然后这个 0 的下一个位置就是新滑动窗口的起始位置。注意,在这个过程中,还要减小滑动窗口的长度。

这样,我们只需要遍历 1 次,不断更新最大长度,就能得到结果。

注意:刚开始时滑动窗口中 0 的个数如果小于 K,我们只拓展窗口,不更新窗口的起始位置(最开始的起始位置为 0)。

Python3 实现:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def longestOnes(self, A: List[int], K: int) -> int:
        sliding_window = 0  # 滑动窗口
        begin = 0  # 滑动窗口的起始位置
        nums0 = 0  # 滑动窗口中0的个数
        max_ = 0
        for i in range(len(A)):
            sliding_window += 1  # 拓展窗口长度
            if nums0 < K:  # 滑动窗口中 0 的个数小于 K,只拓展窗口
                if A[i] == 0:
                    nums0 += 1
            elif nums0 == K:
                if A[i] == 0:  # 如果再有 0 出现,更新滑动窗口
                    while A[begin] == 1:  # 找到滑动窗口中第10的位置
                        begin += 1
                        sliding_window -= 1
                    begin += 1  # 新滑动窗口的起始位置
                    sliding_window -= 1
            max_ = max(max_, sliding_window)  # 更新最大长度
        return max_
问题描述:【Sliding Window、DP、Array】1052. Grumpy Bookstore Owner
解题思路:

方法1(暴力 O(N^2),TLE):

  • 根据 customers 和 grumpy 数组,可以统计出不使用 X 技巧能得到的一个初始的满意度总和;
  • 再考虑使用 X 技巧,对于每个位置,将长度为 X 的窗口中 grupmy[i] == 1 的 custpmers[i] 也加入到初始满意度中,然后更新最大满意度。

这样,时间复杂度为 O(N*X),由于 X 也可能达到 N 的长度级别,因此为 O(N^2),超时。

方法2(DP O(N^2),勉强 AC):

尝试了一下动态规划,虽然时间复杂度还是 O(N^2),但勉强 AC 了。DP 思路如下:

  • 用 dp1[N] 记录不使用 X 技巧的累加初始满意度,dp2[N] 记录使用 X 技巧的最大满意度,最后 dp2[-1] 就是答案;
  • dp1[N] 的状态转移方程很容易 dp1[i] = (dp1[i-1] + customers[i-1]) if grumpy[i-1] == 0 else dp1[i-1]
  • dp2[N] 的状态转移方程为:dp2[i] = (dp2[i-1] + customers[i-1]) if grumpy[i-1] == 0 else max(dp2[i-1], dp1[i-X] + sum(customers[i-X:i])),含义是如果 grumpy[i-1] 为 0,则老板不会生气,dp[i] 直接在 dp2[i-1] 的基础上加上 customers[i-1] 就好;如果 grumpy[i-1] 为 1,则老板生气,dp2[i] 的值取决于 dp2[i-1] (前面已经生过气)和 dp1[i-X] + sum(customers[i-X:i]) (当前生气,最大满意度为前 dp1[i-X] 和这段 X 长度大小的窗口中的数字之和)的最大值。
  • 初始时 dp[i] 中 i < X,无论生气与否,dp2[i] = dp2[i-1] + customers[i-1],因为 X 技巧可以充分展现。

但是,实际上这种做法还是 O(N*X) 的时间复杂度,但是竟然勉强 AC 了(可能脸好吧)。

Python3 实现(DP):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def maxSatisfied(self, customers: List[int], grumpy: List[int], X: int) -> int:
        N = len(customers)
        dp1 = [0] * (N + 1)  # 不使用 X 技巧的累加初始满意度
        dp2 = [0] * (N + 1)  # 使用 X 技巧的最大满意度
        for i in range(1, N + 1):
            if grumpy[i-1] == 0:
                dp1[i] = dp1[i-1] + customers[i-1]
            else:
                dp1[i] = dp1[i-1]
        for i in range(1, N + 1):
            if grumpy[i-1] == 0 or i-X-1 < 0:
                dp2[i] = dp2[i-1] + customers[i-1]
            else:
                dp2[i] = max(dp2[i-1], dp1[i-X] + sum(customers[i-X:i]))
        return dp2[-1]

方法3(Sliding Window O(N),AC):

这也是一道经典的利用滑动窗口解决问题的题目。

我们来定义本题的滑动窗口:因为肯定当技能 X 发挥时能获得的满意度最大,且这个窗口是连续的,因此窗口的大小是固定的。长度为 X 的滑动窗口中记录增加的满意度。

  • 先求出不使用 X 技巧的初始满意度;
  • 因为窗口中记录使用 X 技巧增加的满意度,所以它等于窗口中 grumpy[i] 为 1 的所有 customers[i] 之和;
  • 窗口每次都向右移动一位,刚开始窗口大小小于 X,那么只要是 grumpy[i] == 1 就增加满意度(因为可以充分发挥 X 技巧);当窗口大小等于 X 时,滑动过程中始终保持 X 长度;
  • 当窗口大小等于 X,如果出现一个 grumpy[j] == 1,则窗口增加满意度 customers[j];同时,如果移出去的 grumpy[j-X] == 1,那么滑动窗口的满意度要减去满意度 customers[j-X];
  • 每次移动窗口,都更新使用 X 技巧增加的满意度的最大值;
  • 最后,初始满意度加上使用 X 技巧增加的满意度的最大值就是总的最大满意度。

这样,时间复杂度为 O(N)。

Python3 实现(Sliding Window):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def maxSatisfied(self, customers: List[int], grumpy: List[int], X: int) -> int:
        N = len(customers)
        initial_satisfied = sum([customers[i] for i in range(N) if grumpy[i] == 0])  # 初始的满意度
        sliding_window = 0  # 大小为X的滑动窗口中保存增加的满意度
        add_satisfied = 0  # 大小为X的滑动窗口中增加的满意度的最大值
        for i in range(N):
            if i < X and grumpy[i] == 1:  # 没有达到窗口大小
                sliding_window += customers[i]
            elif i >= X:
                if grumpy[i] == 1:
                    sliding_window += customers[i]  # 滑动窗口中增加当前满意度
                if grumpy[i-X] == 1:
                    sliding_window -= customers[i-X]  # 滑动窗口移除满意度
            add_satisfied = max(add_satisfied, sliding_window)
        return initial_satisfied + add_satisfied  # 两者之和为最终满意度
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.06.17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Leetcode | 第B节:数组综合题(2)
抱歉这一节相对隔得时间长了一些再发出来,因为这几天基本上主要时间都在关注东京奥运会的比赛现场。在发表这篇文章的时候,也恰好知道名将苏炳添以9‘83’‘的时间晋级决赛,我认为他可以以这个成绩再拿一次金牌,希望我的预言成真2333
学弱猹
2021/08/06
4320
LeetCode 1052. 爱生气的书店老板(滑动窗口)
今天,书店老板有一家店打算试营业 customers.length 分钟。每分钟都有一些顾客(customers[i])会进入书店,所有这些顾客都会在那一分钟结束后离开。
SakuraTears
2022/01/13
2570
【前缀和的力量:高效解决子数组和矩阵问题的秘笈】—— 蓝桥杯高频热点题型知识点
前缀和(Prefix Sum)是一种常用的算法技巧,用于快速计算数组中某一范围的元素之和。
用户11286421
2025/03/17
1290
【前缀和的力量:高效解决子数组和矩阵问题的秘笈】—— 蓝桥杯高频热点题型知识点
动态规划(八)——子数组系列(求积问题)
这一篇博客我们继续来领略动态规划算法的魅力~准备好了吗~我们发车去探索动态规划的奥秘啦~🚗🚗🚗🚗🚗🚗
用户11352420
2025/05/25
580
动态规划(八)——子数组系列(求积问题)
LeetCode 1052. 爱生气的书店老板(滑动窗口)
今天,书店老板有一家店打算试营业 customers.length 分钟。每分钟都有一些顾客(customers[i])会进入书店,所有这些顾客都会在那一分钟结束后离开。
Michael阿明
2020/07/13
4600
LeetCode 1052. 爱生气的书店老板(滑动窗口)
LeetCode通关:数组十七连,真是不简单
数组基本上是我们最熟悉的数据结构了,刚会写“Hello World”不久,接着就是“杨辉三角”之类的练习。
三分恶
2021/08/10
4040
力扣(LeetCode)刷题,简单+中等题(第32期)
力扣(LeetCode)定期刷题,每期10道题,业务繁重的同志可以看看我分享的思路,不是最高效解决方案,只求互相提升。
不脱发的程序猿
2021/05/08
3150
力扣(LeetCode)刷题,简单+中等题(第32期)
【优选算法篇】解密前缀和:让数组求和变得如此高效(上篇)
前缀和算法是解决一类常见数组问题的高效方法。它的核心价值在于将多次重复计算的部分进行优化,使得对数组的多次区间求和操作能在常数时间内完成。它不仅可以大幅减少时间复杂度,还能够应用于各种问题,如数组求和、子数组的最大/最小和等。
熬夜学编程的小王
2024/12/24
1930
【优选算法篇】解密前缀和:让数组求和变得如此高效(上篇)
【滑动窗口专题】运用小技巧将问题转化为经典滑动窗口求最值问题
今天,书店老板有一家店打算试营业 分钟。每分钟都有一些顾客( )会进入书店,所有这些顾客都会在那一分钟结束后离开。
宫水三叶的刷题日记
2022/04/06
7170
动态规划(七)——子数组系列(求和问题)
题目要求十分简单,想让我们求解数组最大的连续子数组的和,其中数组元素有正数也有负数,我们结合动态规划思想来解决这个问题~
用户11352420
2025/05/23
1120
动态规划(七)——子数组系列(求和问题)
【动态规划】落花人独立,微雨燕双飞 - 8. 01背包问题
说明: 装第一个和第三个物品时总价值最大,但是装第二个和第三个物品可以使得背包恰好装满且总价值最大。 示例2 输入: 3 8 12 6 11 8 6 8
用户11369350
2025/01/24
1100
【动态规划】落花人独立,微雨燕双飞 - 8. 01背包问题
链表、DFS-LeetCode 216、213、148、202(链表归并排序,组合数问题)
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
算法工程师之路
2019/11/14
5420
算法训练之动态规划(四)——简单多状态问题
前面已经提到了这是一种简单多状态的dp问题,那么这个多状态体现在哪里呢?题目要求不可以接受相邻的预约,那么就说明每一个位置的状态可能是选择的,也可能是没有选择的~这就有两个状态了,那么有两个状态我们应该怎么表示呢?我们可以创建两个dp表,接下来我们结合前面的思想来分析一下这道多状态问题~
用户11352420
2025/04/12
730
算法训练之动态规划(四)——简单多状态问题
Golang Leetcode 213. House Robber II.go
版权声明:原创勿转 https://blog.csdn.net/anakinsun/article/details/89043336
anakinsun
2019/04/12
3480
LeetCode 1671. 得到山形数组的最少删除次数(最长上升子序DP nlogn)
LeetCode 5557. 最大重复子字符串 LeetCode 5558. 合并两个链表 LeetCode 5560. 设计前中后队列(deque)
Michael阿明
2021/02/19
5390
LeetCode 1671. 得到山形数组的最少删除次数(最长上升子序DP nlogn)
【LeetCode 239.滑动窗口最大值】三种解法
题目描述:给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。
心谭博客
2020/04/21
7980
动态规划一篇就够了 全网第二详细, 逐步理解, 万字总结
动态规划,一直以来听着就是一种很高深莫测的算法思想。尤其是上学时候算法的第一堂课,老师巴拉巴拉列了一大堆的算法核心思想,贪心、回溯、动态规划... ...,开始感觉要在算法世界里游刃有余的进行解决各种各样牛B问题了,没想到的还是稀里糊涂学过了之后还就真的是学过了(大学的课程还真是一个样子)。再后来才明白,大学的课程一般来说就是入门级讲解,用来开拓眼界的,真正想要有一番自己的见解,必须要在背后下一番辛苦,形成自己的思考逻辑。
Python编程爱好者
2020/09/03
6.6K2
动态规划一篇就够了 全网第二详细, 逐步理解, 万字总结
LeetCode239. 滑动窗口最大值
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。
静谧星空TEL
2021/04/27
5020
Leetcode 【495、835】
抛开移动的过程只看移动完成的结果。记图片左上角为顶点 (0, 0),正方形边长为 N,要使得两张图片有重叠,那么其中一张图片移到的某一点 (x, y) 一定与另外一张图片的顶点 (0, 0) 重合。
echobingo
2019/06/17
5310
搞定大厂算法面试之leetcode精讲8.滑动窗口
搞定大厂算法面试之leetcode精讲8.滑动窗口 视频教程(高效学习):点击学习 目录: 1.开篇介绍 2.时间空间复杂度 3.动态规划 4.贪心 5.二分查找 6.深度优先&广度优先 7.双指针 8.滑动窗口 9.位运算 10.递归&分治 11剪枝&回溯 12.堆 13.单调栈 14.排序算法 15.链表 16.set&map 17.栈 18.队列 19.数组 20.字符串 21.树 22.字典树 23.并查集 24.其他类型题 3. 无重复字符的最长子串 (medium) 方法1.滑动窗口 动画过大
全栈潇晨
2021/11/27
5170
推荐阅读
相关推荐
Leetcode | 第B节:数组综合题(2)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验