给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。
注意:
num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 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。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-k-digits
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:利用单调栈,
从左至右扫描,当前的数还不确定要不要删,先入栈暂存,保留对它的记忆。
123531这样「高位递增」的数,会尽量删低位,不会删递增的高位。
432135这样「高位递减」的数,肯定想干掉高位,让高位变小,尽量变成「高位递增」
所以,如果当前数比栈顶更大,就还是递增态,是满意的,入栈。
如果当前数比栈顶更小,要当机立断删栈顶的数,不管后面有没有更大的,为什么?
因为栈顶的数在高位,删掉它,后面小的顶上,高位变小,优于低位变小
能不能直接不让前导 0 入栈?
加一个判断:栈为空且当前字符为 “0” 时,不入栈。
class Solution {
public:
string removeKdigits(string num, int k) {
int n = num.size();
if(n == 0)
return "0";
string ans = "";
stack<int>s;
for(int i = 0;i < n;++i)
{
while(k > 0 && !s.empty() && num[i] < s.top())
{
s.pop();
k--;
}
if(num[i]=='0' && s.empty())//去除前导0
continue;
s.push(num[i]);
}
//循环完k还没有减少到0
while(k > 0 && !s.empty())
{
s.pop();
k--;
}
while(!s.empty())
{
ans.push_back(s.top());
s.pop();
}
reverse(ans.begin(),ans.end());
return ans.size()==0? "0": ans;
}
};