LeetCode n位数字,移除其中k位,使得结果最小

n位数字,移除其中k位,使得结果最小。

原题链接

更新:基本一样的的题目1673. 找出最具竞争力的子序列

C++代码

class Solution {
public:
    vector<int> mostCompetitive(vector<int>& nums, int k) {
        int cnt = nums.size() - k;

        stack<int> stk;
        for(int& x : nums) {
            while(stk.size() && cnt > 0 && stk.top() > x) stk.pop(), cnt -- ;
            stk.push(x);
        }

        while(cnt --) stk.pop();
        vector<int> res;
        while(stk.size()) res.push_back(stk.top()), stk.pop();
        reverse(res.begin(), res.end());
        return res;
    }
};

思路

不难发现,对于相同前缀的两个数字 34 x 34x 34x 34 y 34y 34y,如果 x < y x < y x<y则前者更小,否则后者更小(或者相等)。

那我们就可以知道:要求最终的结果最小,那么前缀中的数字要尽可能的小。我们知道“小”是相对的,也就是我们需要来选择这个中的哪些数字要被保留下来,成为”小“的数字。

我们来考虑这样一种情况,对于下标 i i i上的数字 d i g i t digit digit,如果他左边(下标 < i <i <i)存在数字比 d i g i t digit digit大,那么 d i g i t digit digit相对来说就是小的数字,应该被保留下来。

算法(单调栈)

到这里我们就需要考虑每一个数字的前面哪些较大的数,并且能够将他们移除(移除的次数 k k k需要大于0),我们可以用一个栈来维护这个数字序列,枚举该序列,假设当前枚举的数字为 x x x,判断栈顶的数字是否大于 x x x,如果大于,则弹出该栈顶元素,继续执行该过程,直到①栈中不存在数字_或者_②栈顶的数字不大于 x x x_或者_③ k = = 0 k == 0 k==0 这些情况的出现,接着我们将当前元素添加到栈中。

到这里我们需要来解释一下为什么只有栈顶的数字大于 x x x才考虑移除栈中的元素。

  • 首先我们考虑栈顶元素小于当前元素的情况,如果我们选择移除栈顶元素,那么数字序列的前缀将变大,不符合题目要求,所以我们不应该移除栈顶元素。

  • 如果当前元素等于栈顶元素,我们考虑紧接着要枚举到的元素 y y y,如果 x < y x < y x<y,那么我们不应该移除 x x x,否则数字序列将从 ∗ x y ∗ *xy* xy变为 ∗ y ∗ *y* y,并且 x < y x < y x<y,显然变化后的数增大了,如果 x > y x > y x>y,那么我们执行上一段中:

    判断栈顶的数字是否大于 x x x,如果大于,则弹出该栈顶元素。

    即可。

算法复杂度

时间复杂度: O ( n ) O(n) O(n),n为数字序列的长度,每个数字至多会被 p u s h ( ) push() push() p o p ( ) pop() pop()一次。

空间复杂度: O ( n ) O(n) O(n),n为数字序列的长度。

C++代码

class Solution {
public:
    string removeKdigits(string num, int k) {
        stack<int> stk;
        for(auto& c : num) {
            int x = c - '0';
            while(stk.size() && k > 0 && stk.top() > x) {
                stk.pop();
                k -- ;
            }
            stk.push(x);
        }

        while(k --) stk.pop();
        string res;
        while(stk.size()) res += stk.top() + '0', stk.pop();
        while(res.size() > 1 && res.back() == '0') res.pop_back();
        if(res.size() == 0) res = '0';
        reverse(res.begin(), res.end());
        return res;
    }
};
posted @ 2023-01-08 15:10  openallzzz  阅读(9)  评论(0编辑  收藏  举报  来源