移掉k位数字
题目
给定一个以字符串表示的非负整数 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。
解题思路
首先,在确定两个数的大小时,从高位开始对比,只要一个数字的相同位数的数大于另一个数该位的数,那么该数就大。利用这个思想,在该题我们可以维护一个单调栈,并维护一个计数器k来保证来确保栈空间内的数字只多不少。
- 栈为空时元素直接进栈。
- 栈不为空时,比较入栈元素和栈顶元素的大小。如果栈顶元素大于入栈元素,出栈栈顶元素,并且计数器k-1,循环此过程。
在上述方法中会有几种特殊情况需要进行处理。
- 数字是单调递增的,那么此时我们需要从栈顶去掉k个元素,剩余的既是返回结果。
- 栈底元素为0,若此时只剩0一个元素,则返回0,否则需要去除前导0。
代码如下:
char * removeKdigits(char * num, int k){
int len = strlen(num);
//top如果从-1开始后面处理会有些麻烦
int top = 0;
char* staic = malloc(sizeof(char) * (len + 1));
for(int i = 0; i < len; i++){
while(top > 0 && num[i] < staic[top] && k){
top--;
k--;
}
staic[++top] = num[i];
}
//如果是递增的在这里前移top
top -= k;
char *ans = malloc(sizeof(char) * (len + 1));
//用flag和continue来去除前导0(学习大佬的😜)
bool flag = true;
int tem = 0;
//从1开始是因为栈的第一个元素无值
for(int i = 1; i <= top; i++){
if(flag && staic[i] == '0'){
continue;
}
flag = false;
ans[tem++] = staic[i];
}
if (tem == 0) {
ans[0] = '0',ans[1] = 0;
} else {
ans[tem] = 0;
}
return ans;
}

浙公网安备 33010602011771号