letcode每日一题-移掉K位数字

项目描述如下:

思路:
我自己想的是使用贪心算法
对于两个相同长度的数字序列,最左边不同的数字决定了这两个数字的大小,例如,对于 A = 1axxxA=1axxx,B = 1bxxxB=1bxxx,
如果 a > ba>b 则 A > BA>B。
基于此,我们可以知道,若要使得剩下的数字最小,需要保证靠前的数字尽可能小。

基于此我的代码实现如下:


public String removeKdigits(String num, int k) {
        LinkedList<Character> tmp=new LinkedList<>();
        int i=0;
        //构建临时结果列表
        for(;i<num.length()-k;i++){
            tmp.add(num.charAt(i));
        }
        for(;i<num.length();i++){
            tmp.add(num.charAt(i));
            //删除一个数字
            removeBig(tmp);
        }
        StringBuilder result=new StringBuilder();
        for(Character charTmp:tmp){
            if(charTmp=='0' && result.length()==0){
                continue;
            }
            result.append(charTmp);
        }
        return result.length()==0?"0":result.toString();
    }

    public void removeBig(LinkedList<Character> tmp){
        char prev=' ';
        int index=-1;
        for(Character charTmp:tmp){
            if(prev!=' '&& prev>charTmp){
                break;
            }
            prev=charTmp;
            index++;
        }
        tmp.remove(index);
    }

然而暴力的实现复杂度最差会达到 O(nk)(考虑整个数字序列是单调不降的),因此我们需要加速这个过程。
考虑从左往右增量的构造最后的答案。我们可以用一个栈维护当前的答案序列,栈中的元素代表截止到当前位置,
删除不超过 k 次个数字后,所能得到的最小整数。根据之前的讨论:在使用 k 个删除次数之前,栈中的序列从
栈底到栈顶单调不降。
因此,对于每个数字,如果该数字小于栈顶元素,我们就不断地弹出栈顶元素,直到
栈为空
或者新的栈顶元素不大于当前数字
或者我们已经删除了 k位数字
上述步骤结束后我们还需要针对一些情况做额外的处理:

如果我们删除了 mm 个数字且 m<km<k,这种情况下我们需要从序列尾部删除额外的 k-mk−m 个数字。
如果最终的数字序列存在前导零,我们要删去前导零。
如果最终数字序列为空,我们应该返回 00。
最终,从栈底到栈顶的答案序列即为最小数。

考虑到栈的特点是后进先出,如果通过栈实现,则需要将栈内元素依次弹出然后进行翻转才能得到最小数。为了避
免翻转操作,可以使用双端队列代替栈的实现。

代码实现如下:


public String removeKdigits(String num, int k) {
        Deque<Character> queue=new LinkedList<>();
        //我们假设num是一个递减的队列
        for(int i=0;i<num.length();i++){
            char tmpChar=num.charAt(i);
            while (!queue.isEmpty() && k>0 && tmpChar<queue.peekLast()){
                queue.pollLast();
                k--;
            }
            queue.offerLast(tmpChar);
        }
        //处理单调递增的队列
        for (int i=0;i<k;i++){
            queue.pollLast();
        }
        StringBuilder result=new StringBuilder();
        while (!queue.isEmpty()){
            char charTmp=queue.pollFirst();
            if(charTmp=='0' && result.length()==0){
                continue;
            }
            result.append(charTmp);
        }
        return result.length()==0?"0":result.toString();
    }

posted @ 2020-12-02 16:37  CodeWangHAHA  阅读(68)  评论(0编辑  收藏  举报