1. 程式人生 > >貪婪策略:數字去掉幾位求最小值實現

貪婪策略:數字去掉幾位求最小值實現

問題分析

在位數固定的前提下,讓高位的數字儘量小,其值就較小。依據此貪婪策略就可以解決這個問題。

如何根據貪婪策略刪除數字呢?總目標是刪除高位較大的數字,具體地相鄰兩位比較,若高位比低位大則刪除高位。

程式碼一般實現:

package com.demo.test.util;

/**
 * @description: 給定一個整數,刪除k個數後,使得剩餘值最小
 * @author: fengze
 * @create: 2018-11-28 11:37
 **/
public class TestRemoveBig {

    public static String getOptimalValue(String value, int k) {

        //校驗輸入值和刪除個數關係
        if (value.length() <= k) {
            return "0";
        }

        //外層迴圈控制刪除次數
        for (int j = 0; j < k; j++) {

            //內層迴圈控制比較次數
            boolean flag = false;
            for (int i = 0; i < value.length() - 1; i++) {

                if (value.charAt(i) > value.charAt(i + 1)) {
                    value = value.substring(0, i) + value.substring(i + 1);
                    flag = true;
                    //每次迴圈刪除一個數
                    break;
                }

            }
            //未刪除數時,將最後一個值刪除
            if (!flag) {
                value = value.substring(0, value.length() - 1);
            }

            //移除前面為0的所有數值

            removeZero(value);


        }
        if (value.length() == 0){

            return "0";
        }

        return value;
    }

    private static void removeZero(String value) {

        for (int i = 0; i < value.length(); i++) {
            if (value.charAt(i) != '0')
                break;
            value = value.substring(1, value.length());


        }
    }

    public static void main(String[] args) {
        System.out.println(getOptimalValue("15397268",8));
    }
}

效率分析:

1.每一次內層迴圈,都需要從頭遍歷所有數字

2.subString方法本身效能不高

         subString方法的底層實現,涉及到了新字串的建立,以及逐個字元的拷貝。這個方法自身的時間複雜度是O(n)。因此,我們應該避免在每刪除以後數字後就呼叫subString方法。

 

高效率實現:

package com.demo.test.util;

/**
 * @description: 給定一個整數,刪除k個數後,使得剩餘值最小(優化實現方案)
 * @author: fengze
 * @create: 2018-11-28 13:38
 **/
public class TestRemoveBigOptimal {

    public static String getOptimalValue(String value, int k) {

        //校驗輸入值和刪除個數關係
        if (value.length() <= k) {
            return "0";
        }
        //刪除後剩餘位數
        int newLenth = value.length() - k;
        //使用陣列將剩餘元素收集
        char[] newValue = new char[newLenth];
        //棧頂元素
        int stackTop = 0;
        //遍歷元素,將符合要求的刪除,不符合要求的放入陣列中
        for (int i = 0; i < value.length() ; i++) {
            //判斷陣列最後放入元素是否比當前值大,大就更換;第一次不進入
            while (stackTop > 0 && newValue[stackTop-1] > value.charAt(i) && k>0) {
                stackTop--;
                k--;

            }
            //更換符合要求數值
            newValue[stackTop++] = value.charAt(i);
        }
        //找到陣列中第一個非0數值
        int zeroNum = 0;
        while(zeroNum < newLenth && newValue[zeroNum] == '0'){
            zeroNum++;
        }
        //返回結果
        return zeroNum == newLenth ? "0" : new String(newValue,zeroNum,newLenth-zeroNum);

    }

    public static void main(String[] args) {
        System.out.println(getOptimalValue("103970609",4));
    }


}

 程式碼中非常巧妙地運用了棧的特性,在遍歷原整數的數字時,讓所有數字一個個入棧,當某個數字需要刪除時,讓該數字出棧。最後,程式把棧中的元素轉化為字串結果。

程式碼只對所有數字遍歷了一趟,遍歷的時間複雜度是O(n),而後把棧轉化為字串的時間複雜度也是O(n),所以最終的時間複雜度是O(n)

同時,程式中利用棧來回溯遍歷過的數字以及刪除數字,所以程式的空間複雜度是O(n)