题目:
Given an integer array nums
and a positive integer k
, return the most competitive subsequence of nums
of size k
.
An array's subsequence is a resulting sequence obtained by erasing some (possibly zero) elements from the array.
We define that a subsequence a
is more competitive than a subsequence b
(of the same length) if in the first position where a
and b
differ, subsequence a
has a number less than the corresponding number in b
. For example, [1,3,4]
is more competitive than [1,3,5]
because the first position they differ is at the final number, and 4
is less than 5
.
Example 1:
Input: nums = [3,5,2,6], k = 2 Output: [2,6] Explanation: Among the set of every possible subsequence: {[3,5], [3,2], [3,6], [5,2], [5,6], [2,6]}, [2,6] is the most competitive.
Example 2:
Input: nums = [2,4,3,3,5,4,9,6], k = 4 Output: [2,3,3,4]
Constraints:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^9
1 <= k <= nums.length
思路:
观察题目我们可以发现,要求返回的数组是在permutation的情况下越小越好,但是又要保证返回的数组长度要等于给定值k。这里其实使用的是单调栈,不过因为返回的是个vector,我们可以直接用vector来代替stack。遍历数组,对于数组中的每个数,无非是两种情况:pop或者push。为了保持单调栈我们需要用while循环进行持续pop,因为可能出现比如1,1,5,6,3这种情况,比如栈内是[1,1,5,6],这时遇到3,我们就需要pop掉5和6再把三压入栈,最后栈内为[1,1,3]。综上所述,while的条件是栈不为空,并且栈顶要大于当前数组中的数字,这两个条件维护了单调栈。同时因为我们需要返回给定长度为k的数组,因此要在pop的同时,数组剩下的元素加上我栈内元素足够制造k长度的数组去返回:数组总长度 - 当前已经遍历的所有数的个数 + 栈内数字个数 需要大于等于k。这里其实也很好理解,前两部分减完其实就是数组内剩下的数的个数,然后它与栈内个数相加要大于等于k即可。在pop完之后,如果发现当前栈的个数不够k,将当前数组中的数压入栈即可。
代码:
class Solution {
public:
vector<int> mostCompetitive(vector<int>& nums, int k) {
vector<int> res;
for(int i=0;i<nums.size();i++)
{
while(res.size()&&res.back()>nums[i]&&i+1+k-res.size()<=nums.size())
res.pop_back();
if(res.size()<k)
res.push_back(nums[i]);
}
return res;
}
};