[leetcode-402-Remove K Digits]
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.
思路:
观察得到,当一个数字序列是增序的时候,删除最大那个数字即满足余下数字最小,比如1254,删除5得到124是最小的。
那么问题转化为,求递增序列,然后将连续递增序列的最大字符删除,k-1,余下的字符串继续刚才的过程。
思路比较简单,但是。。递归写法太耗空间和时间,没法通过最后一个字符串比较长的测试用例。
string removeKdigits(string num, int k) { if(k==0) { if(num == ""||num.length() == 0) return "0"; // if( num[0]!='0')return num; int i =0; while(num[i]=='0')i++; if(i >= num.length())return "0"; return num.substr(i); } int index =0; while(index+1<num.length() && num[index]<=num[index+1] )index++;//找到最大的 string left = num.substr(0,index); string right ; if(index+1<num.length()) right = num.substr(index+1); else right =""; return removeKdigits(left+right,k-1); }
又学习了大牛的方案:
参考自:https://discuss.leetcode.com/topic/59871/two-algorithms-with-detailed-explaination
he first algorithm is straight-forward. Let's think about the simplest case: how to remove 1 digit from the number so that the new number is the smallest possible? Well, one can simply scan from left to right, and remove the first "peak" digit; the peak digit is larger than its right neighbor. One can repeat this procedure k times, and obtain the first algorithm:
string removeKdigits(string num, int k) { while (k > 0) { int n = num.size(); int i = 0; while (i+1<n && num[i]<=num[i+1]) i++; num.erase(i, 1); k--; } // trim leading zeros int s = 0; while (s<(int)num.size()-1 && num[s]=='0') s++; num.erase(0, s); return num=="" ? "0" : num; }
The above algorithm is a bit inefficient because it frequently remove a particular element from a string and has complexity O(k*n).
One can simulate the above procedure by using a stack, and obtain a O(n) algorithm. Note, when the result stack (i.e. res) pop a digit, it is equivalent as remove that "peak" digit.
string removeKdigits(string num, int k) { string res; int keep = num.size() - k; for (int i=0; i<num.size(); i++) { while (res.size()>0 && res.back()>num[i] && k>0) { res.pop_back(); k--; } res.push_back(num[i]); } res.erase(keep, string::npos); // trim leading zeros int s = 0; while (s<(int)res.size()-1 && res[s]=='0') s++; res.erase(0, s); return res=="" ? "0" : res; }