题目 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.
即给定一个非负数值字符串,要求删除k个字符的情况下数值最小。
测试例子
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.
代码
第一版本
/*************************************************************************
> File Name: Solution.cpp
> Author: Duke-wei
> Mail: 13540639584@163.com
> Created Time: 2017年10月13日 星期五 15时12分09秒
************************************************************************/
#include<iostream>
#include<string>
#include<stack>
#include<algorithm>
#include<vector>
using namespace std;
class Solution1{
public:
//首先简化问题,考虑一次去除一个字符的情况,然后去除k次
string removeKdigits(string num, int k) {
if(k==num.size()) return "0";
for(int i=0;i<k;++i){
if(num.size()<=1) return "0";
num = removeone(num);
//去掉头部0
int j = 0;
for(;j<num.size()&&num[j]=='0';++j);
num = num.substr(j);
}
if(num.size()==0) return "0";
return num;
}
//一次去除一个字符,通过找规律发现
//去除一个字符,即开头非递减序列的最后一个
//如1354278 即去除5,5是首个开始递减的字符
//如12477589 去除7
//如7511 去除7
string removeone(string& s){
int i = 0;
for(;i<s.size()-1;++i){
if(s[i]>s[i+1]) break;
}
string ret = s.substr(0,i);
ret += s.substr(i+1);
return ret;
}
};
第二版本
每次删除一个肯定很慢,所有要遍历一次删除k个,发现这k个字符的规律,就可以通过栈来实现删除,从头入栈,发现比栈顶小,则弹出栈顶,即去除一个字符。
class Solution2{
public:
string removeKdigits(string num, int k) {
if(k==num.size()) return "0";
stack<char> sc;
int i=0;
while(k>0){
if(i>=num.size()){
sc.pop();
--k;
}else if(sc.empty()||sc.top()<=num[i]){
sc.push(num[i++]);
}else{
sc.pop();
--k;
}
}
while(i<num.size()) sc.push(num[i++]);
string ret;
while(!sc.empty()){
ret.push_back(sc.top());
sc.pop();
}
reverse(ret.begin(),ret.end());
i=0;
while(i<ret.size()&&ret[i]=='0')++i;
if(i==ret.size()) return "0";
return ret.substr(i);
}
};
第三版本
简化代码,看了大神的代码,简洁,直接用striing替换stack的功能。
class Solution3{
public:
string removeKdigits(string num, int k) {
string ans = ""; // treat ans as a stack in below for loop
for (char c : num) {
while (ans.length() && ans.back() > c && k) {
ans.pop_back(); // make sure digits in ans are in ascending order
k--; // remove one char
}
if (ans.length() || c != '0') { ans.push_back(c); } // can't have leading '0'
}
while (ans.length() && k--) { ans.pop_back(); } // make sure remove k digits in total
return ans.empty() ? "0" : ans;
}
};
思考扩展
- 这题明确了该字符串是非负数值,因此如果数值为负则应该怎么处理?
- 如果要求去除k个后是最大怎么处理?