移掉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;

}
posted @ 2020-12-02 16:44  爱吃_🍓  阅读(114)  评论(0)    收藏  举报