[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;
    }
原文地址:https://www.cnblogs.com/hellowooorld/p/7101971.html