刷题不会系列——栈,一文带你走天下

前言

基本线性数据结构分为栈、队列、列表等。真正的区别在于元素的添加及移除方式。作为书本(盘子)结构,栈的添加及移除操作只发生于同一端(顶端)。最新添加的元素会被最先移除,即LIFO(last-in first-out)。基础基本就这些,话不多说,直接上题手撕。

1. 最大宽度坡

由浅入深,首先看Leecode中等难度的一道题目:最大宽度坡。网址如下:
最大宽度坡
PS:大家可以看题目要求及其它语言的代码,本文主要分析python版本代码。
思路分析:
本题目标在于求解坡的最大宽度,更建模化讲就是寻找右端大于左端的最长子数组,我们称为目标子数组。因此我们只需要先从左到右找到一个单调递减的子数组,这个子数组中的元素是目标子数组的左端,因此起始为原数组第一个元素,后续比它大的肯定不可能是目标子数组的左端。然后从右到左遍历原数组,寻找目标子数组的右端。
解题基本思路如上,现在再具体分析一下代码思路。
首先维护一个单调递减子数组,第一个数肯定为数组A的起始值,逐步进行比较大小和添加,直到最后一个数为数组A的最小值。因为目标是求数组长度,因此维护的子数组存储A的索引而不是数值。
然后进行第二阶段,从右往左遍历数组A,当数值大于左端时,弹出计算长度并存储或舍弃(继续计算肯定长度肯定变小,因此可以停止)。同时因为计算最长的,因此当当前结果大于索引时已经可以停止了。

至此代码如下:

class Solution:
    def maxWidthRamp(self, A: List[int]) -> int:
    	stack = []
    	nums = len(A)
    	for i in range(nums):
    		if not stack or A[stack[-1]] > A[i]:
    			stack.append(i)
	res = 0
	i = nums - 1
	while i > res:
		while stack and A[stack[-1]] <= A[i]:
			res = max(res, i - stack[-1])
			stack.pop()
		i -= 1
	return res

2. 表现良好的最长时间段

再来看一道进一步的题目:表现良好的最长时间段
思路分析:
这道题本质和上一道是一样的,只不过多了一部分的数据预处理。
以输入样例 hours = [9,9,6,0,6,6,9] 为例,大于8 小时的一天记为 1 ,小于等于 8 小时的一天记为 −1 ,生成一个新数组day。这时候关键来了,我们在生成一个新的数组,第一个数为0,此后每个数sum[i]为day前i个数的加和,这样的话sum[j]-sum[i]就成为了最大宽度坡,这个问题就转换为了上个问题。
至此代码如下:

class Solution:
    def longestWPI(self, hours: List[int]) -> int:
        nums = len(hours)
        day = [-1 for i in range(nums)]
        for i in range(nums):
            if hours[i] > 8:
                day[i] = 1

        sum = [0 for i in range(nums+1)]
        for i in range(1, nums+1):
            sum[i] = sum[i-1] + day[i-1]

        stack = []
        for i in range(nums+1):
            if not stack or sum[stack[-1]] > sum[i]:
                stack.append(i)

        res = 0
        i = nums
        while i > res:
            while stack and sum[stack[-1]] < sum[i]:
                res = max(res, i - stack[-1])
                stack.pop()
            i -= 1

        return res

栈的刷题就先讲到这里啦,真正想特别熟练还是得多刷题,这里只是简单的刷题入门经典题目分享哈。又因为本人一向比较懒,各位看官觉得还可以就点赞评论,督促我写出下一篇,么~。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值