给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。
注意:
num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 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。
基本思路:先举一个特例,对于字符串s,仅仅删除一个元素,a)若s=1234,显然删除最后一个元素;b)若s=4321,显然删除第一个元素;c)若s=1243,经过对比发现,删除4时最小。
- 对于长度相同的数,从左向右,第一个不同的数小的值比较小。
- 若一个序列为严格递增时,删除前面的数,会导致值变大。
- 在删除数时,当删除一个逆序数时,如c)中4>3,删除4时,值变小,其他操作值变大,
数据结构的选择,相当于保存了一个单增栈,故可以使用栈结构,亦可以使用双端队列,甚至vector也可以。
注:如果要求剩余的值最大,删除顺序数即可,即stk[top]>num[i]改为stk[top]<num[i]
string removeKdigits(string num, int k) {
int len=num.size();
int top=-1;
string ans="";
if(len<=k)
return "0";
vector<char> stk(num.size());
for(int i=0;i<num.size();i++){
while(top!=-1&&stk[top]>num[i]&&k){ //逆序删除
top--;
k--;
}
stk[++top]=num[i];
}
while(k--){ //若没有删够,此时stk内的元素是非递减序列,只需从后往前删除k个元素即可。
top--;
}
int pos=0;
while(stk[pos]=='0'&&pos<top) //删除前导零,若结果为零,保留最后一位零
pos++;
while(pos<=top)
ans.push_back(stk[pos++]);
return ans;
}
python版本
def removeKdigits(self, num: str, k: int) -> str:
stack=[]
top=-1
for digit in num:
while k and stack and stack[-1]>digit:
stack.pop()
k-=1
stack.append(digit)
remain=len(num)-k
return ''.join(stack[:remain]).lstrip('0') or '0'