持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
题目
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 。
方法一:暴力
思路及解法
根据题意,我们发现 是一个查询数组,逐个查询 中元素右边的第一个更大的值。因此,我们可以暴力地逐个计算 中的每个元素值 在 中对应位置的右边的第一个比 大的元素值。具体地,我们使用如下方法:
-
初始化与 等长的查询数组 。
-
遍历 中的所有元素,不妨设当前遍历到元素为 :
- 从前向后遍历 中的元素,直至找到
- 从 j 开始继续向后遍历,直至找到 ,其中
- 如果找到了 ,则将 置为 ,否则将 置为 。
-
查询数组 即为最终结果。
代码
class Solution {
func nextGreaterElement(_ nums1: [Int], _ nums2: [Int]) -> [Int] {
let m: Int = nums1.count
let n: Int = nums2.count
var res: [Int] = Array.init(repeating: -1, count: m)
for i in 0..<m {
var j: Int = 0
while j < n && nums2[j] != nums1[i] {
j += 1
}
var k: Int = j + 1
while k < n && nums2[k] < nums2[j] {
k += 1
}
res[i] = k < n ? nums2[k] : -1
}
return res
}
}
复杂度分析
-
时间复杂度:,其中 是 的长度, 是 的长度。
-
空间复杂度:。
方法二:单调栈 + 哈希表
思路
我们可以先预处理 ,使查询 中的每个元素在 中对应位置的右边的第一个更大的元素值时不需要再遍历 。于是,我们将题目分解为两个子问题:
-
第 个子问题:如何更高效地计算 中每个元素右边的第一个更大的值;
-
第 个子问题:如何存储第 个子问题的结果。
解法
我们可以使用单调栈来解决第 个子问题。倒序遍历 ,并用单调栈中维护当前位置右边的更大的元素列表,从栈底到栈顶的元素是单调递减的。
具体地,每次我们移动到数组中一个新的位置 ,就将当前单调栈中所有小于 的元素弹出单调栈,当前位置右边的第一个更大的元素即为栈顶元素,如果栈为空则说明当前位置右边没有更大的元素。随后我们将位置 的元素入栈。
因为题目规定了 是没有重复元素的,所以我们可以使用哈希表来解决第 个子问题,将元素值与其右边第一个更大的元素值的对应关系存入哈希表。
代码
class Solution {
func nextGreaterElement(_ nums1: [Int], _ nums2: [Int]) -> [Int] {
var hashmap: [Int : Int] = [:]
var st: [Int] = []
var n = nums2.count - 1
while n >= 0 {
let num: Int = nums2[n]
while !st.isEmpty && num >= st.last! {
st.removeLast()
}
hashmap[num] = st.isEmpty ? -1 : st.last
st.append(num)
n -= 1
}
var res: [Int] = Array.init(repeating: -1, count: nums1.count)
for i in 0..<nums1.count {
res[i] = hashmap[nums1[i]] ?? -1
}
return res
}
}
复杂度分析
-
时间复杂度:,其中 是 的长度, 是 的长度。我们需要遍历 以计算 中每个元素右边的第一个更大的值;需要遍历 以生成查询结果。
-
空间复杂度:,用于存储哈希表。