Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible.
Note:
- The length of num is less than 10002 and will be ≥ k.
- The given num does not contain any leading zero.
Example 1:
Input: num = "1432219", k = 3 Output: "1219" Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest.
Example 2:
Input: num = "10200", k = 1 Output: "200" Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes.
Example 3:
Input: num = "10", k = 2 Output: "0" Explanation: Remove all the digits from the number and it is left with nothing which is 0.
题目的大意是给定一个由字符串表示的数字,在数字中移除其中的K位,使得新的数字最小。
这道题目可以采用贪心算法,就是从字符串的头部向尾部扫,只要发现前面的数字比后面的小就移除前面的这个数字,如果移除的位已经等于k或者已经到达字符串的尾部就停止,如果扫完了字符串后移除的位还不足k,就直接把最后面的位去掉。
因为在字符串前面的数字代表的权重肯定比后面的数字大,所以只要这里的数字能够减小1,肯定比这位不改变而去改变后面的数字所得到的数字小。而如果按照这种方法把整个字符串扫完,那么字符串中的数字肯定是按递增的顺序排列的,所以如果还要继续删除数字,就只需要删除后面的数字就可以了。所以这个算法是正确的。
但是在实现的时候对下标要非常注意,比如在移除了第i个数字以后,还要拿原来的i-1个数字和原来的i+1(现在为i)个数字比较,我在实现的时候就是因为没有考虑到这个问题导致答案错误,还浪费了非常多的时间。由于题目要求把最前面的0去掉,所以最后要特判一下,把最前面的0去掉,如果最后字符串为空,则返回字符串“0”。
这个算法只用了一重循环,但是循环内部使用了erase函数,我并不清楚它的复杂度,如果它的复杂度为O(1)的话,那么这个算法的复杂度为O(n)。
以下为源代码:
class Solution {
public:
string removeKdigits(string num, int k) {
for(int i=0;i<num.size()-1;i++)
{
if(k==0) break;
if(num[i]>num[i+1])
{
num.erase(i,1);
k--;
i-=2;
if(i<-1) i=-1;
}
}
if(k>0)
{
num.erase(num.size()-k,k);
}
int i=0;
while(true)
{
if(num[i]!='0') break;
i++;
}
num.erase(0,i);
if(num.size()==0) return "0";
return num;
}
};