题目:跳转至 402. 移掉K位数字
给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。
注意:
示例 1 :
输入: num = “1432219”, k = 3
输出: “1219”
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。
示例 2 :
输入: num = “10200”, k = 1
输出: “200”
解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。
示例 3 :
输入: num = “10”, k = 2
输出: “0”
解释: 从原数字移除所有的数字,剩余为空就是0。
class Solution {
public:
string removeKdigits(string num, int k) {
}
};
思路:
因为要移除k个数字后剩下的数字最小,数字首位的影响最大。所以,直接就能想到从前往后遍历,如果前一位数字比他后一位更大,就把前一个数字移除,直到移除k个,得出结果。
问题在于,比如4531去除3个,从首位开始算,4<5略过,接下来5>3,5要去掉,然后要比较的不是3>1而是4>3,那比较过的值应该被存储下来,有需要时先进后出的跟其余值比较,用栈就比较明显了。
class Solution {
public:
string removeKdigits(string num, int k) {
stack<int> st;
string res;
int len=num.length();
if(len==0)
return res;
else if(len==1 && k==0)
return num;
else if(len==1 && k==1)
return "0";
bool isSame=true;
for(int i=1;i<len;++i){ //如果全相等
if(num[i]!=num[0])
isSame=false;
}
if(isSame==true){
num.erase(0,k);
return num;
}
int i=1,count=0;
while(count<k && i<=len-count){ //删除k个数,注意循环条件
st.push(i-1);
int temp=st.top();
if(num[temp]>num[i]){
num.erase(temp,1);
st.pop();
++count;
--i; //因为从num中去除了一个数
}
++i;
}
i=0;
while(num[i]=='0') //排除首位0
num.erase(i,1);
if(count<k)
num.erase(num.length()-k+count);
if(num.length()==0)
num="0";
return num;
}
};
问题很多emmmm,结构也有点乱提交后有很多没想到的状况。比如相等的数去除,所有值都是升序排列,极端条件下值是空还是0这些都没考虑到,东拼西凑,还有点其他问题。
放弃挣扎,看题解,大佬就都很厉害。
class Solution {
public:
string removeKdigits(string num, int k) {
vector<char> stk;
for (auto& digit: num) { //没减满k个数时,一边存前一个数的值,一边比较
while (stk.size() > 0 && stk.back() > digit && k) {
stk.pop_back();
k -= 1;
}
stk.push_back(digit);
}
for (; k > 0; --k) //考虑上面没有去掉k接下来都是升序排列的情况,去除后面的值
stk.pop_back();
string ans = "";
bool isLeadingZero = true;
for (auto& digit: stk) { //去0
if (isLeadingZero && digit == '0') {
continue;
}
isLeadingZero = false;
ans += digit;
}
return ans == "" ? "0" : ans;
}
};
比较起来,写法上最大的不同点是我只用栈来存储第一步比较时候的值,而实际上可以把所有值都丢进去。最关键的,先想明白可能的情况再开始写代码。