📅  最后修改于: 2023-12-03 15:07:59.877000             🧑  作者: Mango
圆形数组是一种特殊的数组,其最后一个元素与第一个元素相邻,即数组的起点和终点相连。举个例子,一个普通的数组 [1, 2, 3, 4, 5]
可以用一个圆形数组 [1, 2, 3, 4, 5, 1]
来表示。
给定一个圆形数组 nums
,对于其中的每一个元素 nums[i]
,需要找出它在圆形数组中下一个更大的元素。如果不存在更大的元素,则将其置为 -1。
例如,给定圆形数组 nums = [5, 4, 3, 2, 1]
,应该返回数组 [-1, 5, 5, 5, 5]
。
注意:圆形数组中的所有元素都是非负整数,且长度不超过 1000。
最简单的方法是枚举每一个元素,然后从当前位置向后依次查找下一个更大的元素。由于是圆形数组,我们需要用取模运算计算出下一个位置的索引。
时间复杂度为O(n^2),空间复杂度为O(1)。
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
n = len(nums)
ans = [-1] * n
for i in range(n):
for j in range(i + 1, n + i):
if nums[j % n] > nums[i]:
ans[i] = nums[j % n]
break
return ans
我们可以使用单调栈来优化这个算法。首先将第一个元素入栈,然后遍历每一个元素。如果当前元素比栈顶元素大,说明当前元素就是栈顶元素的下一个更大的元素,将栈顶元素弹出,并将其下一个更大的元素存储在结果数组中。重复这个过程,直到当前元素比栈顶元素小为止。
当遍历完整个数组后,有可能栈中还剩余一些元素,这表示它们没有下一个更大的元素。我们只需要将它们的结果置为 -1 即可。
由于是圆形数组,我们需要把数组长度扩大一倍,在遍历之前把数组中的每一个元素拷贝一遍到末尾。这样,当我们到达数组的末尾时,就可以取模回到数组的起点了。
时间复杂度为O(n),空间复杂度为O(n)。
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
n = len(nums)
nums += nums
ans = [-1] * n
stack = []
for i, num in enumerate(nums):
while stack and nums[stack[-1]] < num:
ans[stack.pop()] = num
if i < n:
stack.append(i)
return ans
圆形数组中查找下一个更大的元素的问题,可以用暴力枚举和单调栈两种方法来解决。单调栈的时间复杂度为O(n),比暴力枚举要快得多。这里需要注意,圆形数组需要扩大一倍,并在遍历之前把数组中的每一个元素拷贝一遍到末尾,这样才能让算法正确处理环形数组的情况。