范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

万字长文字节跳动面试高频算法题(先码再看)

  今天给大家带来一篇 面试高频算法题之栈&队列的详细解析,全文包含9道大厂笔试面试算法真题,一举拿下栈和队列这个知识点 ,让算法不在成为进入大厂的绊脚石。1栈和队列
  全文概览
  基础知识栈
  栈是一种先进后出的数据结构。这里有一个非常典型的例子,就是堆叠盘子。我们在放盘子的时候,只能从下往上一个一个的放;在取的时候,只能从上往下一个一个取,不能从中间随意取出。
  栈是一种操作受限的线性表,只允许在一端处理数据。主要包括两种操作,即入栈和出栈,也就是在栈顶插入一个数据和从栈顶删除一个数据。
  栈既可以用数组实现,也可以用链表来实现。用数组实现的栈,我们叫作顺序栈,用链表实现的栈,我们叫作链式栈。 队列
  队列是一种先进先出的数据结构。你可以把它想象成排队买票,先来的先买,后来的人只能站末尾,不允许插队。
  队列跟栈一样,也是一种操作受限的线性表数据结构。主要包括两个操作,即出队和入队,也就是从队首取一个元素和在队尾插入一个元素。
  队列可以用数组来实现,也可以用链表来实现。用数组实现的队列叫作顺序队列,用链表实现的队列叫作链式队列。 2用两个栈实现队列
  剑指 Offer 09. 用两个栈实现队列 问题描述
  用两个栈来实现一个队列,完成 n 次在队列尾部插入整数 (push) 和在队列头部删除整数 (pop) 的功能。队列中的元素为 int 类型。保证操作合法,即保证pop操作时队列内已有元素。
  示例:
  输入:["PSH1","PSH2","POP","POP"]
  返回值:1,2
  说明:
  "PSH1":代表将1插入队列尾部 "PSH2":代表将2插入队列尾部 "POP":代表删除一个元素,先进先出 => 返回1 "POP":代表删除一个元素,先进先出 => 返回2 分析问题
  首先,我们需要知道队列和栈的区别。 队列是一种先进先出的数据结构。队列中的元素是从后端入队,从前端出队。就和排队买票一样。 栈是一种后进先出的数据结构。栈中的元素是从栈顶压入,从栈顶弹出。
  为了使用两个栈实现队列的先进先出的特性,我们需要用一个栈来反转元素的入队顺序。
  入队操作Push:
  因为栈是后进先出的,而队列是先进先出的,所以要想使用栈来实现队列的先进先出功能,我们需要把新入栈的元素放入栈底。为了实现这个操作,我们需要先把栈S1中的元素移动到S2,接着再把新来的元素压入S2,然后再把S2中的所有元素再弹出,压入到S1。这样就实现了把新入栈的元素放入栈底的功能。
  def push(self, node):         # write code here         while self.stack1:             self.stack2.append(self.stack1.pop())         self.stack2.append(node)         while self.stack2:             self.stack1.append(self.stack2.pop())
  出队操作Pop:
  我们直接从S1弹出就可以了,因为经过反转后,S1中的栈顶元素就是最先入栈的元素,也就是队首元素。     def pop(self):         if self.stack1:             return self.stack1.pop()
  我们来看完整的代码实现。 class Solution:     def __init__(self):         self.stack1 = []         self.stack2 = []     def push(self, node):         # write code here         while self.stack1:             self.stack2.append(self.stack1.pop())         self.stack2.append(node)         while self.stack2:             self.stack1.append(self.stack2.pop())      def pop(self):         if self.stack1:             return self.stack1.pop()
  我们可以看到入队操作的时间复杂度是O(n),空间复杂度也是O(n)。出队时间复杂度是O(1),空间复杂度也是O(1)。 优化
  在上面的算法中,不知道你有没有发现,每次在push一个新元素时,我们都需要把S1中的元素移动到S2中,然后再从S2移回到S1中。这显然是冗余的。其实,我们在入队时只需要插入到S1中即可。而出队的时候,由于第一个元素被压在了栈S1的底部,要想实现队列的先进先出功能,我们就需要把S1的元素进行反转。我们可以把栈S1的元素Pop出去,然后压入S2。这样就把S1的栈底元素放在了栈S2的栈顶,我们直接从S2将它弹出即可。一旦 S2 变空了,我们只需把 S1 中的元素再一次转移到 S2 就可以了。
  下面我们来看一下代码实现。 class Solution:     def __init__(self):         self.stack1 = []         self.stack2 = []     def push(self, node):         # write code here         self.stack1.append(node)      def pop(self):         if not self.stack2:             while self.stack1:                 self.stack2.append(self.stack1.pop())         return self.stack2.pop() 3有效的括号
  LeetCode 20. 有效的括号 问题描述
  给定一个只包括  "(" ,")" ,"{" ,"}" ,"[" ,"]"  的字符串 s  ,判断字符串是否有效。
  有效字符满足的条件是: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。
  示例:
  输入:s = "()[]{}"
  输出:true 分析问题
  这个问题我们可以借助 "栈" 这种数据结构来解决。在遍历字符串的过程中,当我们遇见一个左括号时,我们就入栈,当我们遇到一个右括号时,我们就取出栈顶元素去判断他们是否是同类型的。如果不是的话,那就代表字符串s不是有效串,我们直接返回False。如果是,接着去遍历,直到遍历结束为止。当遍历完字符串s后,如果栈为空,就代表字符串是有效的。这里需要注意一点,为了加快判断左、右括号是否是同类型的,我们引入哈希表存储每一种括号。哈希表的键为右括号,值为相同类型的左括号。
  下面我们来看一下代码实现。 def isValid(s):     #如果字符串不是偶数,直接返回false     #因为字符只包含括号,所以只有偶数时才有可能匹配上     if len(s) % 2 == 1:         return False      dict = {         ")": "(",         "]": "[",         "}": "{",     }      stack = list()      for ch in s:         #代表遍历到右括号         if ch in dict:             #看栈顶元素是否能匹配上,如果没有匹配上,返回false             if not stack or stack[-1] != dict[ch]:                 return False             #如果匹配上,弹出栈顶元素             stack.pop()         else:             #匹配到左括号,入栈             stack.append(ch)     #栈为空,代表s是有效串,否则是无效串     return not stack 4包含min函数的栈
  剑指 Offer 30. 包含min函数的栈 问题描述
  定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数,并且调用 min函数、push函数 及 pop函数 的时间复杂度都是 O(1)。
  push(value):将value压入栈中
  pop():弹出栈顶元素
  top():获取栈顶元素
  min():获取栈中最小元素
  示例: minStack.push(-2); -->将-2入栈 minStack.push(0);  -->将0入栈 minStack.push(-3); -->将-3入栈 minStack.min();    -->返回栈中最小元素-3 minStack.pop();    -->弹出栈顶元素-3 minStack.top();    -->返回栈顶元素0 minStack.min();    -->返回栈中最小元素-2 分析问题
  对于普通的栈来说,执行push和pop的时间复杂度是O(1),而执行min函数的时间复杂度是O(N),因为要想找到最小值,就需要遍历整个栈,为了降低min函数的时间复杂度,我们引入了一个辅助栈。 数据栈A :栈A用来存储所有的元素,保证入栈push、出栈pop、获取栈顶元素top的操作。 辅助栈B :栈B用来存储栈A中所有 非严格递减 的元素,即栈A中的最小值始终在栈B的栈顶,这样可以保证以O(1)的时间复杂度来返回栈中的最小值。
  下面我们来看一下代码实现。 class Solution:     def __init__(self):         #数据栈         self.A = []         #辅助栈         self.B = []     #push操作     def push(self, x):         self.A.append(x)         #如果辅助栈B为空,或者栈顶元素大于x,则入栈         if not self.B or self.B[-1] >= x:             self.B.append(x)      def pop(self):         #弹出数据栈A中的元素         s = self.A.pop()         #如果弹出的元素和栈B的栈顶元素相同,则为了保持一致性         #将栈B的栈顶元素弹出         if s == self.B[-1]:             self.B.pop()      def top(self):         #返回数据栈A中的栈顶元素         return self.A[-1]      def min(self):         #返回辅助栈B中的栈顶元素         return self.B[-1] 5表达式求值问题描述
  请写一个整数计算器,支持加减乘三种运算和括号。
  示例:
  输入:"(2 * (3 - 4)))* 5"
  返回值:-10 分析问题
  因为只支持加、减、乘、括号,所以我们根据优先级可以分为3类,即括号>乘>加、减,假设先把括号去掉,那么就剩下乘和加减运算,根据运算规则,我们需要先计算乘、再计算加、减,因此我们可以这么来考虑,我们先进行乘法运算,并将这些乘法运算后的整数值返回原表达式的相应位置,则随后整个表达式的值,就等于一系列整数加减后的值。而对于被括号分割的表达式,我们可以递归的去求解,具体算法如下。
  遍历字符串s,并用变量preSign记录每个数字之前的运算符,初始化为加号。 遇到空格时跳过。 遇到数字时,继续遍历求出这个完整的数字的值,保存到num中。 遇到左括号时,需要递归的求出这个括号内的表达式的值。 遇到运算符或者表达式的末尾时,就根据上一个运算符的类型来决定计算方式。 如果是加号,不需要进行计算,直接push到栈里 如果是减号,就去当前数的相反数,push到栈里 如果是乘号,就需要从栈内pop出一个数和当前数求乘法,再把计算结果push到栈中 最后把栈中的结果求和即可。
  下面我们来看一下代码实现。 class Solution:     def calculate(self, s):         n = len(s)         #存取部分数据和         stack = []         preSign = "+"         num = 0         i=0         while i0:                     if s[j]=="(":                         counts=counts+1                     if s[j]==")":                         counts=counts-1                     j=j+1                 #剥去一层括号,求括号内表达式的值                 num=self.calculate(s[i+1:j-1])                 i=j-1              if not c.isdigit() or i==n-1:                 if preSign=="+":                     stack.append(num)                 elif preSign=="-":                     stack.append(-1*num)                 elif preSign=="*":                     tmp=stack.pop()                     stack.append(tmp*num)                  num=0                 preSign=c             i=i+1         return sum(stack)  s=Solution() print(s.calculate("(3+4)*(5+(2-3))")) 6滑动窗口的最大值
  LeetCode 239. 滑动窗口最大值 问题描述
  给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。
  示例:
  输入:[2,3,4,2,6,2,5,1],3
  输出:[4,4,6,6,6,5] 分析问题
  这道题的关键点在于求滑动窗口中的最大值。大小为k的滑动窗口,我们可以通过遍历的方式来求出其中的最大值,需要O(k)的时间复杂度。对于大小为n的数组nums,一共有n-k+1个窗口,因此该算法的时间复杂度是O(nk)。
  通过观察,我们可以知道,对于两个相邻的滑动窗口,有k-1个元素是共用的,只有一个元素是变化的,因此我们可以利用此性质来优化我们的算法。
  对于求最大值问题,我们可以使用优先级队列(大顶推)来求解。首先,我们将数组的前k个元素放入优先级队列中。每当我们向右移动窗口时,我们就可以把一个新的元素放入队列中,此时堆顶元素就是堆中所有元素的最大值,然而这个最大值有可能不属于当前的滑动窗口中,我们需要将该元素进行移除处理(如果最大值不在当前滑动窗口中,它只能在滑动窗口的左边界的左侧,所以滑动窗口向右移动的过程中,该元素再也不会出现在滑动窗口中了,所以我们可以对其进行移除处理)。我们不断地移除堆顶的元素,直到其确实出现在滑动窗口中。此时,堆顶元素就是滑动窗口中的最大值。
  为了方便判断堆顶元素与滑动窗口的位置关系,我们可以在优先队列中存储二元组 (num,index),表示元素num在数组中的下标为index。
  小trick:因为python中只提供了小顶堆,所以我们需要对元素进行取反处理,例如对于列表[1, -3],我们对元素进行取反,然后插入小顶堆中,此时堆中是这样的[-1,3],我们取出堆顶元素-1,然后取反为1,正好可以得到列表中的最大值1。
  我们nums=[2,3,4,2,6,2,5,1],k=3为例,来看一下具体的过程。 首先,我们将nums的前3个元素放入优先级队列中,队首元素下标值index=2>0,在窗口中,所以加入结果中,此时res=[4]。 下一个元素2入队,此时队首元素下标index=2>1,在窗口中,所以加入结果中,此时res=[4,4]。 下一个元素6入队,此时队首元素下标index=4>2,在窗口中,所以加入结果中,此时res=[4,4,6]。 下一个元素2入队,此时队首元素下标index=4>3,在窗口中,所以加入结果中,此时res=[4,4,6,6]。 下一个元素5入队,此时队首元素下标index=4=4,在窗口中,所以加入结果中,此时res=[4,4,6,6,6]。 下一个元素1队列,此时队首元素下标index=4<5,不在窗口中,所以我们将其弹出,此时队首元素的下标变为6,在窗口中,所以加入结果中,此时res=[4,4,6,6,6,5]。 进阶
  这道题我们也可以使用双端队列来求解。我们在遍历数组的过程中,不断的对元素对应的下标进行出队入队操作,在出入队的过程中,我们需要保证队列中存储的下标对应的元素是从大到小排序的。具体来说,当有一个新的元素对应的下标需要入队时,如果该元素比队尾对应的元素的值大,我们需要弹出队尾,然后循环往复,直到队列为空或者新的元素小于队尾对应的元素。
  由于队列中下标对应的元素是严格单调递减的,因此队首下标对应的元素就是滑动窗口中的最大值。但是此时的最大值可能在滑动窗口左边界的左侧,并且随着窗口向右移动,它永远不可能出现在滑动窗口中了。因此我们还需要不断从队首弹出元素,直到队首元素在窗口中为止。
  我们还是以nums=[2,3,4,2,6,2,5,1],k=3为例,来看一下具体的过程。我们首先初始化一个空队列que。 此时队列为que空,元素2对应的下标0入队。并且此时未形成窗口,不取值。 此时队列que=[0],队尾元素为0,它对应数组中的元素是nums[0] < nums[1]的,所以我们把队尾0弹出,此时队列为空,我们将1入队。并且此时未形成窗口,不取值。 此时队列que=[1],队尾元素为1,它对应的数组中的元素是nums[1] < nums[2]的,所以我们把队尾1弹出,此时队列为空,我们将2入队。并且此时队首元素2在窗口[0,2]中,所以取出队首元素。 此时队列que=[2],队尾元素为2,它对应的数组中的元素是nums[2] > nums[3]的,所以我们将3入队。并且此时队首元素2在窗口[1,3]中,所以取出队首元素。 此时队列que=[2,3],队尾元素为3,它对应的数组中的元素是nums[3] < nums[4]的,所以我们把队尾3弹出,并且此时队尾元素对应的数组中的元素是nums[2] < nums[4],所以我们把队尾2弹出,此时队列为空,我们将4入队。并且此时队首元素4在窗口[2,4]中,所以取出队首元素。 此时队列que=[4],队尾元素为4,它对应的数组中的元素是nums[4] > nums[5]的,所以我们将5入队。并且此时队首元素4在窗口[3,5]中,所以我们取出队首元素。 此时队列que=[4,5],队尾元素为5,它对应的数组中的元素是nums[5] < nums[6]的,所以我们把队尾5弹出,此时队尾元素对应的数组中的元素时nums[4] > nums[6] ,所以我们将6入队。并且此时队首元素4在窗口[4,6]中,所以我们取出队首元素。 此时队列que=[4,6],队尾元素为6,它对应的数组中的元素是nums[6] > nums[7]的,所以我们将7入队。而此时队首元素4不在窗口[5,7]中,所以我们将其移除队列,此时队首元素6在窗口[5,7]中,所以我们将其取出。
  下面我们来看一下代码实现。 import collections class Solution:     def maxSlidingWindow(self, nums, k):         n = len(nums)         #申请一个双端队列         q = collections.deque()          #初始化第一个窗口         for i in range(k):             #如果队列不为空且比队尾元素大,将队尾出队             while q and nums[i] >= nums[q[-1]]:                 q.pop()             #直到队列为空,或者比队尾元素小,入队             q.append(i)          #将队首元素加入结果中         ans = [nums[q[0]]]          #窗口逐步向右移动         for i in range(k, n):             #如果队列不为空且比队尾元素大,将队尾出队             while q and nums[i] >= nums[q[-1]]:                 q.pop()             #直到队列为空,或者比队尾元素小,入队             q.append(i)             #如果队首元素不在该窗口内,出队操作             while q[0] <= i - k:                 q.popleft()             #将队首元素加入结果中             ans.append(nums[q[0]])          return ans   s=Solution() print(s.maxSlidingWindow([2,3,4,2,6,2,5,1],3)) 7栈和排序问题描述
  给你一个由1~n,n个数字组成的一个排列和一个栈,要求按照排列的顺序入栈。如何在不打乱入栈顺序的情况下,仅利用入栈和出栈两种操作,输出字典序最大的出栈序列。
  排列:指 1 到 n 每个数字出现且仅出现一次。
  示例:
  输入:[2,4,5,3,1]
  输出:[5,4,3,2,1] 分析问题
  由于我们只能使用出栈和入栈两种操作,要想使得出栈序列字典序最大,首先想到的就是令高位尽可能地大,我们出栈的时机就是:当前入栈元素若是大于之后将要入栈的元素,那么就将其出栈。当元素出栈后,还需要判断栈顶元素与之后将要入栈元素之间的大小关系,如果此时栈顶元素大于之后将要入栈的元素,那么就将其出栈,不断判断直到栈为空或条件不满足。
  为了快速判断"当前入栈元素是否大于之后将要入栈的元素",我们需要创建一个辅助数组temp,其中temp[i]表示i之后的最大元素。借助辅助数组,我们可以以O(1)的时间复杂度去判断当前入栈元素是否大于之后将要入栈的元素。
  下面我们来看一下代码的实现。 import sys class Solution:     def solve(self , a):         n=len(a)         res=[]         if n==0:             return res         stack=[]         temp=[0]*n         temp[n-1]=-sys.maxsize-1         #从右往左遍历数组a,然后取填充temp         #使得temp[i]表示i之后的最大元素         for i in range(n-2,-1,-1):             temp[i]=max(a[i+1],temp[i+1])          #遍历数组a         for i in range(0,n):             if a[i] > temp[i]:  #若当前元素大于之后将要入栈的元素,将其加入结果中                 res.append(a[i])                 # 若栈不为空,且栈顶元素大于temp[i],                 # 栈顶出栈,加入结果中                 while stack and stack[-1] > temp[i]:                     res.append(stack[-1])                     stack.pop()             else:                 stack.append(a[i])          while stack:             res.append(stack[-1])             stack.pop()         return res
  该算法的时间复杂度是O(n),空间复杂度也是O(n)。 8单调栈问题描述
  给定一个长度为 n 的可能含有重复值的数组 arr ,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。请设计算法,返回一个二维数组,表示所有位置相应的信息。位置信息包括:两个数字 l 和 r,如果不存在,则值为 -1,下标从 0 开始。
  示例:
  输入:[3,4,1,5,6,2,7]
  输出:[[-1,2],[0,2],[-1,-1],[2,5],[3,5],[2,-1],[5,-1]] 分析问题
  这道题最简单的解法就是暴力求解,即通过两层for循环来求解。如下所示: class Solution:     def foundMonotoneStack(self , nums):         n=len(nums)         res=[]         #遍历一遍数组         for i in range(0,n):             l=-1             r=-1             #从左往右寻找l,寻找比nums[i]小的最近的nums[l]             for j in range(0,i):                 if nums[j] < nums[i]:                     l=j              #从右往左寻找l,寻找比nums[i]小的最近的nums[r]             for j in range(n-1,i,-1):                 if nums[j] < nums[i]:                     r=j              res.append([l,r])         return res
  该算法的时间复杂度是O(n^2),空间复杂度是O(1)。
  显然暴力求解的时间复杂度太高,那我们该如何优化呢?其实这道题我们可以使用单调栈来求解,首先我们来看一下单调栈的定义。
  单调栈是指栈内元素是具有有单调性的栈,和普通栈相比,单调栈在入栈的时候,需要将待入栈的元素和栈顶元素进行对比,看待加入栈的元素入栈后是否会破坏栈的单调性,如果不会,直接入栈,否则一直弹出到满足条件为止。
  本题中,我们维护一个存储数组下标的单调栈。然后遍历数组,执行如下操作。
  我们以 求每一个i左边离i最近且小于arr[i]的位置 为例,来看一下算法的执行流程。首先我们从左往右遍历数组。假设遍历到的元素是 arr[i],栈顶元素 top 对应的数组中的元素是 arr[top],然后我们拿 arr[i] 和 arr[top] 进行对比。 如果 arr[top] > arr[i],就说明 top 不是第 i 个元素的解,也不会是 i 以后任何元素的解(因为 i 比 top 距离后面的数更近,同时arr[i] < arr[top]),所以我们就把top弹出,直到栈为空或者栈顶元素(数组的下标)对应数组中的元素小于 arr[i]。 如果arr[top] < arr[i],就说明第 i 个数的解就是 top,因为栈内的元素都是单调递增的,所以 top 是离 i 最近的数,即 top 就是所求值。然后因为 i 可能是 i 右侧的候选解,所以把 i 加入栈中。
  同理,我们从右往左遍历数组,就可以得到 每一个i右边离i最近且小于arr[i]的位置 。
  下面我们来看一下代码的实现。 class Solution:     def foundMonotoneStack(self , nums):         n=len(nums)         res=[]         l=[0]*n         r=[0]*n         #单调栈         stack=[]         #从左往右遍历数组         for i in range(0,n):             #如果栈顶元素top对应的数组中的元素num[top]>nums[i]             #则出栈,直到栈为空或者栈顶元素对应的数组中的元素比nums[i]小             while stack and nums[stack[-1]] >=nums[i]:                 stack.pop()              l[i]=stack[-1] if stack else -1             #i入栈,因为i有可能成为i右边的答案             stack.append(i)          stack=[]         #从右往左遍历数组         for i in range(n-1,-1,-1):             # 如果栈顶元素top对应的数组中的元素num[top]>nums[i]             # 则出栈,直到栈为空或者栈顶元素对应的数组中的元素比nums[i]小             while stack and nums[stack[-1]] >= nums[i]:                 stack.pop()             r[i] = stack[-1] if stack else -1             # i入栈,因为i有可能成为i左边的答案             stack.append(i)          for i in range(0,len(l)):             res.append([l[i],r[i]])          return res  s=Solution() print(s.foundMonotoneStack([3,4,1,5,6,2,7]))
  该算法的时间复杂度是O(n),空间复杂度是O(n)。 9每日温度
  739. 每日温度 问题描述
  请根据每日气温列表  temperatures  ,计算在每一天需要等几天才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0  来代替。
  示例:
  输入:temperatures = [73,74,75,71,69,72,76,73]
  输出:[1,1,4,2,1,1,0,0] 分析问题
  既然是求每一天需要等几天才会有更高的温度,那么最直观的想法就是针对气温列表 temperatures 中的每个温度值,向后依次进行搜索,找到第一个比当前温度更高的值的位置索引,然后减去当前温度所在的位置索引,就是要求的结果。
  下面我们来看一下代码的实现。 class Solution(object):     def dailyTemperatures(self,temperatures):         #求出温度列表的长度         n = len(temperatures)         result=[0]*n         #遍历每一个温度值         for i in range(n):             if temperatures[i]<100:                 #想后搜索第一个大于当前温度值的元素                 for j in range(i+1,n):                     if temperatures[j] > temperatures[i]:                         result[i]=j-i                         break          return result
  该算法的时间复杂度是O(n^2),空间复杂度是O(n)。
  显然该算法的时间复杂度太高,那我们有什么优化的方法吗。 优化
  这里可以使用单调栈来优化,即维护一个温度值下标的单调栈,使得从栈顶到栈底的的元素对应的温度值依次递减。具体来说,我们正向遍历温度列表 temperatures。对于温度列表中的每个元素 temperatures[i]。如果栈为空,则直接将 i 进栈;如果栈不为空,则比较栈顶元素 prev 对应的温度值 temperatures[prev] 和 当前温度 temperatures[i]。 如果 temperatures[prev] < temperatures[i],则将栈顶元素 prev 移除,此时 prev 对应的等待天数为 i - prev。重复上述操作直到栈为空或者栈顶元素对应的温度大于等于当前温度,然后将 i 进栈。 如果 temperatures[prev] > temperatures[i],则直接将元素 i 入栈。
  下面我们来思考一个问题,为什么可以在出栈的时候更新等待天数 result[prev] 呢?因为即将进栈的元素 i 对应的温度值 temperatures[i] 一定是 temperatures[prev] 右边第一个比它大的元素。
  下面我们来看一个具体的例子,假设温度列表 temperatures = [73,74,75,71,69,72,76,73] 。
  初始时,单调栈 stack 为空;等待天数 result 为 [0,0,0,0,0,0,0,0]。
  下面我们来看一下代码的实现。 n = len(temperatures)         #初始化一个空的栈         stack = []         result = [0] * n         for i in range(n):             temperature = temperatures[i]             #如果 temperatures[i] 大于栈顶元素对应的温度值,则栈顶元素出栈。             while stack and temperature > temperatures[stack[-1]]:                 prev = stack.pop()                 result[prev] = i - prev             stack.append(i)         return result
  该算法的时间复杂度是O(n),空间复杂度也是O(n)。
  原文链接:https://mp.weixin.qq.com/s/0Uv7UBKk0tzhWHLQCePmIg

买二手手机选择闲鱼还是转转很多人不解,为什么要二手平台做对比,二手东西不都一样的吗?其实虽然都叫二手平台,但是从模式上来讲还是有很大差别的,可能不同的人喜欢不同的模式,所以我就来说说,看你适合哪一种。闲鱼首平板手机秒变生产力PC,制表修图无难度,向日葵智能远控鼠标试玩一个不足百元的鼠标产品,通过简单操作就可以变成生产力工具,更神奇的是还可以实现你远程办公的梦想,你相信吗?没错,就是这款向日葵MM110智能远控鼠标。初见这款向日葵MM110智能远苹果公司轻易宣布暂停在俄服务,那我们以后还能买苹果手机吗?民族的命运只能掌握在自己手里。年轻人们,早点抛弃苹果!否则,一旦中美发生冲突,你们将成为最惨的人,一可以定位你们,泄露你们的信息,二可以停止关键服务!不能买了买个苹果辩不停,如今打情况有多糟十年后发现丢失的iPhone堵塞了厕所浴室管道发出的奇怪撞击声让马里兰州的一位居民发现她丢失的2012年的iPhone堵塞在马桶里。据美国版太阳报报道,马里兰州居民贝基贝克曼(BeckiBeckmann)在事情发生在她6种价格实惠的蓝牙耳机替代品,让您不花钱的情况下享受完美音质选择AirPods或其他品牌的无线耳机会带来很多好处。首先,在行动自由方面,没有电线可以让您在解放双手的同时四处走动,它是运动的完美配件。像AirPods这样谨慎的无线耳机也很舒适实战总结的7个C程序,好东西不私藏在学习和工作开发的时候,经常需要使用到各种各样不太常用的操作,这种情况一般是自己手动写一些小程序来处理。因为它们不太常用,所以经常用了又没保存,等到下一次在使用的时候又需要重写,这世卫组织8种预防人工智能年龄歧视的方法根据世界卫生组织最近的一份政策简报,解释说人工智能在医疗保健中使用的数据可能无法代表老年人。简报解释说,人工智能是其算法的产物,如果为算法提供数据的数据偏向于年轻人,人工智能可能会甘肃省综合科技创新水平指数增幅居全国第8位我省综合科技创新水平指数增幅居全国第8位每日甘肃网3月1日讯据兰州晚报报道记者从日前举行的2022年甘肃省科技工作会议上获悉,我省综合科技进步水平居全国第23位西部第5位,保持在全银华全球新能源车量化优选股票发起式(QDII)基金首发3月1日,资本邦了解到,银华全球新能源车量化优选股票发起式(QDII)今日发行,基金全称为银华全球新能源车量化优选股票型发起式证券投资基金(QDII)A银华全球新能源车量化优选股票小米公司悄然上架新机,全球限量200套,仅3999元售价亲民物以稀为贵,数量越少的东西往往也会更受欢迎,而在手机行业中,多家手机厂商均发布过限量版手机,不过同样都是限量版手机也还是有区别的,有的限量版机型是手机厂商们盈利的手段,其价格偏高,前功尽弃Meta解散ARVR操作系统团队3月1日消息,据外媒报道,Meta已经解散了一个由300名员工组成的团队,该团队致力于为其AR和VR设备开发新的操作系统。据了解,该团队将与Meta的其他部门分享其经验。其中一些人
刘强东的一双龙凤!女儿被宠成了公主,儿子却成为他一生的痛近年来,越来越多的人喜欢在京东上购买电器。京东不仅诚信经营,而且有完善的售后服务。我自己也是金牌会员,我们花钱买安心和舒适,更是买一个放心。随着京东的成长,京东的老板刘强东也成为公华为刚宣布新消息,谷歌便急着推出新系统,外媒却泼冷水差距明显导语在美国的各种针对性打压下,华为发展之路艰难,但这也让华为开始走上自主研发之路。华为鸿蒙系统最近几年也是闹得沸沸扬扬,很多人都对其寄予厚望,期待它能走向市场和安卓抗衡,让我国实现天猫京东掐架,iPhone成了罪魁祸首,库克我招谁惹谁了?一年一度的618大促还未到来,各家电商就开始提前进入到了战场,今年给我们的感觉好像比每年都要精彩许多,当然火药味最足的当时天猫和京东的苹果大战,这也让一众果粉兴奋不已,当然我们说的这群程序员中的广告狂人,把抖音广告做成了AR游戏在大部分人印象里,广告总是占据屏幕却平平无奇。但现在,广告也可以有丰富的玩法和有趣的互动,充满创新。比如,你在刷抖音的时候,有没有玩过这些AR互动广告?瞄准悬浮在空中的菜品,它们就一周体验后,iOS14。6痛改前非,重新做人了吗?我这次足足使用一星期后才发表总结的文章,原因想必IQ超过120的各位肯定都知道,那就是上个版本的iOS14。5。1实在太坑爹,狠起来连自己的当代旗舰iPhone12ProMax都一特斯拉又现刹车失灵?官方车主制造舆论,想免费换新大家还记得鸭鸭前几天写过的特斯拉要整培训班的事情吧?培训班里有没有新故事,鸭鸭并不知道,但是关于特斯拉刹车失灵的事情倒是又发生了。。事情的经过还要从河南的温先生说起。据他介绍,最近BampampampO发布BeosoundExplore户外蓝牙音箱铝合金外壳,1598元IT之家5月31日消息丹麦厂商BangOlufsen近日正式推出了该品牌首款户外蓝牙音箱BeosoundExplore。这款产品拥有防水设计,坚固耐用,圆柱形的设计利于抓握,方便用我买我用我来说这不是一个智能眼镜boseframe当初bose这个智能眼镜才出来的时候,满怀购买的冲动智能眼镜,ar导航,bose音效加持,虽然是墨镜但是可以自己配镜片,无限美好,这颜值,这功能,能打!那么实际用下来是什么情况呢?iPhone13屏幕开始生产,确认支持高刷新屏幕丨AirPods3今年底推出iPhone13高刷屏生产之前就有消息表示,台积电已经提前给苹果准备生产A15处理器,其性能相比A14提升并不大,毕竟目前苹果处理器已经处于一个性能溢出状态。而根据最新的报道显示,从手机多摄到智能汽车ARVR,欧菲光等光学企业纷纷瞄准新方向在手机摄影领域,从过去的大底竞赛,到后来长焦之战,再到近两年的潜望式镜头,镜头技术的革新无疑成为了手机影像发展的主旋律。今年上半年,液态镜头的关注度也被提高。有手机摄像头产业人士对同一商品,我只想买小!大数据ampampquot精准推送ampampquot会让我更省钱吗?我一直觉得现在手机里的各种吃喝玩乐APP对人性的观察简直无孔不入,不然为何我上一秒还在和家人讨论周末的晚上要不要吃螺蛳粉,下一秒我的外卖APP开始给我自动推送附近排名第一的螺蛳粉商