leetcode在力扣 App 中打开
调试中...
调试中...
题目描述
题目描述
题解
题解
提交记录
提交记录
代码
代码
测试用例
测试用例
测试结果
测试结果
全部题解
【LetMeFly】1673.找出最具竞争力的子序列:单调栈(贪心)
108
2024.05.24
发布于 北京
贪心
数组
C++

Problem: 1673. 找出最具竞争力的子序列

  1. 解题方法:单调栈

    1. 方法概述

    2. 具体怎么做

    3. 为什么这么做

    4. 时空复杂度

    5. AC代码

      1. C++
      2. Java
      3. Python

解题方法:单调栈

先看做法,再讲原理(可能看完做法不看原理就懂了)。

方法概述

使用一个单调递增栈。和普通单调栈不同的是,本题需要同时确保:

  1. 单调栈中最多有个元素
  2. 如果要出栈,要先保证出栈后

然后问题基本上就解决了。

具体怎么做

使用一个栈用来存放最终答案,然后遍历数组:

栈顶元素>当前元素栈顶出栈后还能凑够k个时,栈顶元素不断出栈。

若栈中元素个数小于k,则当前元素入栈。

遍历完成后,从栈底到栈顶的元素即为要找的答案。

为什么这么做

需要明白的是,“只要后面元素还够,遇到小的元素时小元素越往前越好”:

例如当前栈中是[2 4 6k = 3,剩余元素是3 1000 1000 1000 ...

当前遍历到了元素3,后面元素足够多,那么3就应该尽量往前(把4 6都替换掉变成[2 3)。

虽然3后面的元素都很大,但是[2 3 ∞是优于[2 4 6的。

为什么“若栈中元素个数小于k,则当前元素入栈”:

因为“若当前元素较小”或者“栈中元素不是很足”,那当前元素当然要入栈。

否则(栈中元素数量为)的话,说明当前元素很大,没给栈中元素弹出来,当前元素不值得入栈。

时空复杂度

  • 时间复杂度
  • 空间复杂度,栈中最多同时存在个元素

AC代码

C++

class Solution {
public:
    vector<int> mostCompetitive(vector<int>& nums, int k) {
        stack<int> st;
        for (int i = 0; i < nums.size(); i++) {
            while (st.size() && st.top() > nums[i] && (st.size() - 1) + (nums.size() - i) >= k) {
                st.pop();
            }
            if (st.size() < k) {
                st.push(nums[i]);
            }
        }
        // stack -> vector
        vector<int> ans;
        while (st.size()) {
            ans.push_back(st.top());
            st.pop();
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};

Java

// import java.util.ArrayDeque;
// import java.util.Deque;

class Solution {
    public int[] mostCompetitive(int[] nums, int k) {
        Deque<Integer> st = new ArrayDeque<Integer>();
        for (int i = 0; i < nums.length; i++) {
            while (!st.isEmpty() && st.peek() > nums[i] && (st.size() - 1) + (nums.length - i) >= k) {
                st.pop();
            }
            if (st.size() < k) {
                st.push(nums[i]);
            }
        }
        // stack -> array
        int[] ans = new int[k];
        for (int i = k - 1; i >= 0; i--) {
            ans[i] = st.pop();
        }
        return ans;
    }
}

Python

# from typing import List

class Solution:
    def mostCompetitive(self, nums: List[int], k: int) -> List[int]:
        st = []
        for i in range(len(nums)):
            while st and st[-1] > nums[i] and (len(st) - 1) + (len(nums) - i) >= k:
                st.pop()
            if len(st) < k:
                st.append(nums[i])
        return st

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

评论 (0)
行 1,列 1
nums =
[3,5,2,6]
k =
2
Source