找出最具竞争力的子序列
难度:
标签:
题目描述
代码结果
运行时间: 90 ms, 内存: 28.2 MB
/*
* 思路:虽然Stream API并不是为这种需要索引的操作而设计的,
* 但我们可以使用一个辅助栈和普通循环来实现这个问题的解。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public int[] mostCompetitive(int[] nums, int k) {
Stack<Integer> stack = new Stack<>();
int n = nums.length;
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && stack.peek() > nums[i] && stack.size() + n - i > k) {
stack.pop();
}
if (stack.size() < k) {
stack.push(nums[i]);
}
}
return stack.stream().mapToInt(i -> i).toArray();
}
}
解释
方法:
题解采用单调栈的思路来解决问题。具体方法是遍历输入数组 nums,使用栈(stack)存储潜在的最具竞争力的子序列。对于每个元素 num,首先检查栈顶元素是否大于当前元素 num,并且检查是否还有足够的剩余元素(remain)可以从栈中移除。如果条件满足,则将栈顶元素弹出,这样做是为了保持栈中的元素尽可能小以形成最具竞争力的子序列。此外,每弹出一个元素,remain就减少1,表示可以丢弃的元素数减少。最后,将当前元素 num 压入栈中。遍历结束后,栈中可能的元素数量大于 k,因此只取前 k 个元素作为结果。这种方法确保了在满足长度为 k 的条件下,得到的子序列是最小的。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么题解中选择使用单调栈来求解最具竞争力的子序列,而不是其他数据结构如堆或优先队列?
▷🦆
题解中提到,当栈顶元素大于当前元素并且还可以移除元素时就弹出栈顶元素,这种操作是否会导致某些情况下无法得到真正的最具竞争力的子序列?
▷🦆
在题解的while循环中,对remain的条件检查(remain > 0)是如何确保最终的栈中仍然能保留足够的元素以满足长度为k的要求?
▷