LeetCode402-移掉K位数字
给定一个以字符串表示的非负整数 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。
一、思路
(一)贪心算法
一个很明显的移除方法是找出所有的:
n
u
m
[
i
]
>
n
u
m
[
i
+
1
]
num[i]>num[i + 1]
num[i]>num[i+1]
删除num[i+1]
也就是说:前一个(高位)数比后一个(低位)数要更大,则删除前一个(高位)数。这个想法很好理解,就是使用更小的数字去取代原来的高位数字,这么一来num的数值就变小了。
我们假设k足够大,反复执行该操作,会使得num变成一个非递减数,也就是说其中的数字从高位到低位是非递减的。
对于非递减数num,我们需要做的是不断移除num中最大的数字,因为该数是非递减的,所以最大的数字一定是在最后面。
最后,删除前导0,判断num是否为空就行了。
1、将num变为非递减数
非递减数:“123455567899”
递增数:“123456789”
有两种情况:
- k不足够大。假设num至少需要删除n个数,才能变为非递减数,而n > k,那么我们至少要让num的前面部分变为非递减的
- k足够大。直接将之变为非递减数。
代码:
for (int i = 1; i < num.size(); i++) {
while (k && i >= 1 && num[i] < num[i - 1]) {
num.erase(i - 1, 1);
i--;
k--;
}
}
2、对于非递减数的处理
从末位开始删除数字,直到k=0为止
综合以上两点,代码:
class Solution {
public:
string removeKdigits(string num, int k) {
if (k >= num.size())
return "0";
for (int i = 1; i < num.size(); i++) {
while (k && i >= 1 && num[i] < num[i - 1]) {
num.erase(i - 1, 1);
i--;
k--;
}
}
while (k) {
num.pop_back();
k--;
}
while (num.size() && num[0] == '0'){
num.erase(0, 1);
}
return num.empty() ? "0" : num;
}
};