代码随想录算法训练营第四期第五十八天 | 739. 每日温度、496.下一个更大元素 I

文章提供了解决两个与单调栈相关的问题的Python代码实现。第一个问题是给定一个整数数组表示每天的温度,返回一个数组,表示对于每一天,下一个更高温度出现的天数。第二个问题是找到一个子集数组中的元素在原数组中的下一个更大元素。两个问题都利用了单调栈的特性,即栈内元素从栈顶到栈底递增,以此来有效地查找目标元素。
摘要由CSDN通过智能技术生成

739. 每日温度

# 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温
# 在这之后都不会升高,请在该位置用 0 来代替
#
# 示例 1:
# 输入: temperatures = [73,74,75,71,69,72,76,73]
# 输出:[1,1,4,2,1,1,0,0]
#
# 示例 2:
# 输入: temperatures = [30,40,50,60]
# 输出:[1,1,1,0]
#
# 示例 3:
# 输入: temperatures = [30,60,90]
# 输出: [1,1,0]
#
# 提示:
# 1 <=temperatures.length <= 105
# 30 <=temperatures[i]<= 100
1.单调栈的存放元素:
存放元素的下标i

2.单调栈的元素顺序:
从栈顶到栈底递增,即栈底的元素一定是最大的

3.判断条件如下:
a.当前遍历温度小于栈顶下标温度
b.当前遍历温度等于栈顶下标温度
以上情况相同,可直接入栈对应下标
c.当前遍历温度大于栈顶下标温度
res[栈顶元素] = 当前下标-栈顶元素,出栈
如果当前下标温度依旧大于栈顶下标温度
重复上述步骤,要保证栈底元素是最大的

class Solution:
    def dailyTemperatures(self, temperatures: [int]) -> [int]:
        # 有点迷糊
        stack= [0]
        res = [0] * len(temperatures)
        for i in range(1,len(temperatures)):
            if temperatures[i] < temperatures[stack[-1]]:
                stack.append(i)
            elif temperatures[i] == temperatures[stack[-1]]:
                stack.append(i)
            else:
                while stack and temperatures[i] > temperatures[stack[-1]]:
                    res[stack[-1]] = i - stack[-1]
                    stack.pop()
                stack.append(i)
        return res
        # 暴力法,超时了
        # res = []
        # for i in range(len(temperatures)):
        #     flag = 1
        #     for j in range(i+1, len(temperatures)):
        #         if temperatures[j] > temperatures[i]:
        #             res.append(j-i)
        #             flag = 0
        #             break
        #     if flag:
        #         res.append(0)
        # return res
if __name__ == '__main__':
    temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
    temperatures = [30, 40, 50, 60]
    temperatures = [30, 40, 90]
    tmp = Solution()
    res = tmp.dailyTemperatures(temperatures)
    print(res)

496.下一个更大元素 I  

# nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。
# 给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
# 对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。
# 如果不存在下一个更大元素,那么本次查询的答案是 -1 。
# 返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。
#
# 示例 1:
# 输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
# 输出:[-1,3,-1]
# 解释:nums1 中每个值的下一个更大元素如下所述:
# - 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
# - 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
# - 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
#
# 示例 2:
# 输入:nums1 = [2,4], nums2 = [1,2,3,4].
# 输出:[3,-1]
# 解释:nums1 中每个值的下一个更大元素如下所述:
# - 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
# - 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。
#
# 提示:
# 1 <= nums1.length <= nums2.length <= 1000
# 0 <= nums1[i], nums2[i] <= 104
# nums1和nums2中所有整数 互不相同
# nums1 中的所有整数同样出现在 nums2 中
解法2的思路:

1.单调栈的存放元素:
存放元素的下标i

2.单调栈的元素顺序:
这里有两个列表,因为nums2更全,所以这里遍历nums2;
但是单调栈是对应nums1的,所以这里res的长度是nums1的长度;
这里赋初始值都是-1,这样只需要修改部分值;
从栈顶到栈底递增,即栈底的元素一定是最大的

3.判断条件如下:
a.当前遍历数字小于栈顶下标对应数字
b.当前遍历数字等于栈顶下标对应数字
以上情况相同,可直接入栈对应下标
c.当前遍历数字大于栈顶下标数字
注意:这个情况出现了两个数字,第一个是栈顶元素对应数字,第二个是遍历的数字,这个数字是更大的;
这里因为是求nums1的单调栈,所以要先判断栈顶元素是否存在于nums1,如果存在就处理,不存在就不用处理;
如果存在,取这个栈顶元素在nums2里对应的值在nums1里面的索引:index = nums1[i].index(nums2[stack[-1]])
res[index] = nums2[i],出栈
出栈之后,如果当前遍历数字依旧大于栈顶下标数字
重复上述步骤,要保证栈底元素是最大的
from typing import List
class Solution:
    # 在看完了上一题之后,尝试了很多次,琢磨了出来,虽然距离卡哥的答案多了不少步骤,但写出来
    # 了不是,哎,以及不得不感叹,卡哥的解法很优雅
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        size = len(nums2)
        res = [-1] * len(nums1)
        tmp = [0] * size # 我在这里仍然按照739题的思路多建立了一个列表,但是要返回的列表是res
        stack = [0]
        for i in range(1,size):
            if nums2[i] <= nums2[stack[-1]]:
                stack.append(i)
            else:
                while stack and nums2[i] > nums2[stack[-1]]:
                    top = stack.pop()
                    tmp[top] = i - top
                stack.append(i)
        for i in range(len(nums1)):
            index = nums2.index(nums1[i]) # 这里取当前值在nums2的索引
            if tmp[index] != 0: # 不等于0则说明后面有超过当前值的值
                # index是当前值在nums2的索引,tmp纪录超过当前值多少位,是大于当前值的值
                res[i] = nums2[index+tmp[index]]
        return res


    def nextGreaterElement2(self, nums1: List[int], nums2: List[int]) -> List[int]:
        result = [-1]*len(nums1)
        stack = [0]
        for i in range(1,len(nums2)):
            # 情况一情况二
            if nums2[i]<=nums2[stack[-1]]:
                stack.append(i)
            # 情况三
            else:
                while len(stack)!=0 and nums2[i]>nums2[stack[-1]]:
                    # 在出栈之前处理栈顶元素,如果该元素存在于nums1,就处理
                    if nums2[stack[-1]] in nums1:
                        # 这里是针对nums1建的result,所以取栈顶元素对应的在nums1里面的索引
                        index = nums1.index(nums2[stack[-1]])
                        result[index]=nums2[i] # 这里刚好,当前值大于栈顶元素
                    stack.pop()
                stack.append(i)
        return result

if __name__ == '__main__':
    nums1 = [4, 1, 2]
    nums2 = [1, 3, 4, 2]
    nums1 = [2, 4]
    nums2 = [1, 2, 3, 4]
    nums1 = [1, 3, 5, 2, 4]
    nums2 = [6, 5, 4, 3, 2, 1, 7]
    tmp = Solution()
    res = tmp.nextGreaterElement(nums1,nums2)
    print()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值