503. 下一个更大元素 II
给定一个循环数组 nums
( nums[nums.length - 1]
的下一个元素是 nums[0]
),返回 nums
中每个元素的 下一个更大元素 。
数字 x
的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1
。
示例 1:
输入: nums = [1,2,1] 输出: [2,-1,2] 解释: 第一个 1 的下一个更大的数是 2; 数字 2 找不到下一个更大的数; 第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
n = len(nums)
result = [-1] * n
stack = []
for i in range(2*n):
while stack and nums[i % n] > nums[stack[-1]]:
result[stack.pop()] = nums[i % n]
if i < n:
stack.append(i)
return result
2*n单纯是为了满足如果第一次从=从头到尾没有找到元素的下一个更大值,就要从头再找一遍因此是两倍数组长度,入栈的时候要满足i<n
笨方法
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
double_arr, n = nums + nums, len(nums)
ans = [-1] * n
for i in range(n):
j = i + 1
while j < n + i:
if double_arr[j] > double_arr[i]:
ans[i] = double_arr[j]
break
j += 1
return ans
变型:1019. 链表中的下一个更大节点
给定一个长度为 n
的链表 head
对于列表中的每个节点,查找下一个 更大节点 的值。也就是说,对于每个节点,找到它旁边的第一个节点的值,这个节点的值 严格大于 它的值。
返回一个整数数组 answer
,其中 answer[i]
是第 i
个节点( 从1开始 )的下一个更大的节点的值。如果第 i
个节点没有下一个更大的节点,设置 answer[i] = 0
。
示例 1:
输入:head = [2,1,5] 输出:[5,5,0]
思路:
对每个数,寻找它下一个更大元素
其实就是从尾巴开始往前遍历,如果遍历到的数大于栈顶,则栈顶出栈,直到栈顶有大于这个数的值,那么这个值就是答案,或者栈顶为空,表示这个数后面都没有比他更大的值了,那么他就是最大值,这两种情况后都要把这个值去栈,然后再继续取前面一个节点,因为这个节点可能是前一个结点的较大值。这样一直遍历到node为空
代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def nextLargerNodes(self, head: Optional[ListNode]) -> List[int]:
ans = []
st = [] # 单调栈(节点值)
def f(node: Optional[ListNode], i: int) -> None:
if node is None:
nonlocal ans
ans = [0] * i # i 就是链表长度
return
f(node.next, i + 1)
while st and st[-1] <= node.val:
st.pop() # 弹出无用数据
if st:
ans[i] = st[-1] # 栈顶就是第 i 个节点的下一个更大元素
st.append(node.val)
f(head, 0)
return ans
这串代码十分巧妙
递归方式,开头判断当前node是否为空,这样当node为空的时候,就能求出来链表的长度,同时因为return了,所以直接跳转到最后一个节点开始进行下面的while操作,也就自然的完成了从尾巴开始遍历的需求!!
方法二:不使用递归,直接反转链表,这样再从反转后的链表从头结点遍历,相当于从尾巴开始,不过这里要注意,因为此时是倒着记录答案,因此返回的时候要把答案反转
代码:
class Solution:
# 206. 反转链表
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
pre = None
cur = head
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
def nextLargerNodes(self, head: Optional[ListNode]) -> List[int]:
head = self.reverseList(head)
ans = []
st = [] # 单调栈(节点值)
while head:
while st and st[-1] <= head.val:
st.pop() # 弹出无用数据
ans.append(st[-1] if st else 0) # 栈顶就是第 i 个节点的下一个更大元素
st.append(head.val)
head = head.next
return ans[::-1] # 由于是倒着记录答案的,返回前要把答案反转