要求:已知一个使用字符串表示的非负整数num,将num中的k个数字移
除,求移除k个数字后,可以获得的最小的可能的新数字。
分析:
- 为了使新数字更小,从最左端到最右端,每位数字尽可能最小。
- 通过一个单调栈(栈底——栈顶:单调增),遍历整个字符串,将其每个字符入栈;
- 入栈过程中,将栈顶元素与需要入栈字符进行对比,若栈顶元素较大,则弹出栈顶元素,将较大字符入栈;
- 每次出栈后,同时由于移除了一个元素,需要将k-1;
各种特殊情况
:
如果是i==0结束的循环, 则 k 可能不等于0, 移除掉stk末尾k个元素;
如果是k==0结束的循环, 则 i 可能不等于0, 需要加上num中i之后的元素.
去除掉开头的零,同时保证在全是零的情况下返回一个0;
class Solution {
public:
string removeKdigits(string num, int k) {
std::vector<int> data;
std::string result="";
int number=0;
//if(num.size()<=0){
// return 0;
// }
for(int i=0;i<num.length();i++){
number=num[i]-'0';
//注意while的几个条件顺序不能换,否则出错
while(data.size()!=0 && data[data.size()-1]>number && k>0){
data.pop_back(); k--;
}
if(number!=0 || data.size()!=0){
data.push_back(number);
}
}
while(k>0 && data.size()!=0){
data.pop_back();
k--;
}
for(int j=0;j<data.size();j++){
result.append(1,data[j]+'0');
}
if(result==""){
result="0";
}
return result;
}
};
通过更改while()循环体顺序出现错误信息如下:
while( data[data.size()-1]>number && data.size()!=0 && k>0) //error
错误消息
:Line 923: Char 34: runtime error: pointer index expression with base 0x000000000000 overflowed to 0xfffffffffffffffc (stl_vector.h)
所以切记正确的循环体顺序为:
while(data.size()!=0 && data[data.size()-1]>number && k>0)
再贴出一个参考代码
算法思想都相同,实现方法不同:
class Solution {
public:
string removeKdigits(string num, int k) {
stack<char> st;
/* for(int i=0;i<num.length();i++) */
for (auto c : num) {
while (!st.empty() && st.top() > c && k > 0) {
st.pop();// 循环体中顺序不能换,导致错误
--k;
}
if (st.empty() && c == '0') continue;
st.push(c);
}
while (!st.empty() && k > 0) {
st.pop();
--k;
}
string res;
while (!st.empty()) {
res += st.top();
st.pop();
}
reverse(res.begin(), res.end());
return res.empty() ? "0" : res;
}
};