LeetCode 402. Remove K Digits

309 阅读1分钟

LeetCode 402. Remove K Digits

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

  示例 1 :

输入:num = "1432219", k = 3 输出:"1219" 解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。 示例 2 :

输入:num = "10200", k = 1 输出:"200" 解释:移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。 示例 3 :

输入:num = "10", k = 2 输出:"0" 解释:从原数字移除所有的数字,剩余为空就是 0 。  

提示:

1 <= k <= num.length <= 105 num 仅由若干位数字(0 - 9)组成 除了 0 本身之外,num 不含任何前导零

算法1

(贪心) O(n)

思路:尽可能让最高位小,最高位相同的情况下尽可能让次高位小,所以应该维护一个非递减栈。

构建一个非递减栈stk:从左往右遍历数字num,依次进栈;每个数字x进栈前检查是否比栈顶,是的话弹掉栈顶;全部数字一共有k次机会弹栈顶(相当于,最多在这一步删掉k个数字) 如果k次(删数字的)机会没有用完,则弹出栈顶直到stk中剩余stk.size()−k个数字,将stk倒出来再reverse,统计前导0的个数,并以此返回对应的值 举例,在Example 1中,输入为 num = “1432219”, k = 3,输出为”1219”。

第一步,构造stk

的步骤是, (stk=1,k=3) –> (stk=14,k=3) –> (stk=13,k=2) –> (stk=12,k=1) –> (stk=122,k=1) –> (stk=12,k=0) –> (stk=121,k=0) –> (stk=1219,k=0)

第二步,k已经等于0了

第三步,(stk=1219) –> (res=”9121”) –> (res=”1219”) –> i=0,res.substr(i)=”1219“

相关语法小细节:最后return调用的res.substr(i)

string.substr(start , [length]) :返回一个从指定位置开始的指定长度的子字符串

string.substring(start, end) :返回位于 String 对象中指定位置的子字符串。

C++ 代码

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

        while (k -- ) stk.pop();

        string res;
        while (stk.size())
        {
            res += stk.top();
            stk.pop();
        }
        reverse(res.begin(), res.end());
        int i = 0;
        while (i < res.size() && res[i] == '0') i++;
        if (i == res.size()) return "0";
        return res.substr(i);
    }
};