o(n)時間複雜度查找所有元素後面第一個比他大的數

說明

  1. 輸入n個無序整數
    輸出 每個數之後第一個比他大的數,要求時間o(n)

    示例:
    1,-1,2,3
    輸出:
    2 2 3

解決思路:棧+棧底指針
邏輯:
棧中存儲元素位置索引
int bottom=0;// 初始化棧底索引

分析:

注意時間複雜度是o(n) 說明是只需要遍歷一次,如果沒這個限制,會自然而然想到兩層循環遍歷
解決方式:棧+棧底指針
輸入:input[]
輸入第i個元素

  1. 棧爲空,i=入棧, bottom =i
  2. 輸入>棧底元素,那麼棧中需要全部出棧(始終保持棧底是最大元素),執行1
  3. 輸入<=棧底元素,不能直接入棧,(因爲可能棧頂元素比較小,那麼新元素就是棧頂元素的後面的第一個比他大的元素)
    3.1 輸入<= 棧頂元素 ,直接入棧
    3.2 輸入> 棧頂元素,出棧,再入棧 (3.1,3.2 保證元素從棧底->棧頂保持非減順序)(入棧前注意是否需要更新bottom指針)
  4. 輸入遍歷完,棧中還剩餘的元素則是不能找見之後比他大的元素

java代碼實現:

將輸出的序列放在了新的數組之中(也可以修改原數組)


/**
 * @author wangwei
 * @date 2019/3/7 14:03
 * @classDescription 輸入是一個無無序數組
 * 輸出:每個元素的之後一個第一個比自己大的元素
 * 要求o(n) 的時間複雜度
 */
public class FindFirstBiggerAfterSelf {

    public int [] solution(int[] input) {
        if(null==input||0==input.length){
            return  null ;
        }
        Stack<Integer> stack = new Stack<>();
        int bottom = 0; // 初始化棧底指針
        int [] result=new int[input.length];// 記錄搜索結果

        for (int i = 0; i < input.length; i++) {
        //1. 棧空
            if (stack.isEmpty()) {
                bottom = i;
                stack.push(i);
                continue;
            }
            // 棧底是棧中最大元素
            // 假設棧中是  3  1
            // 輸入是  2     3>2  入棧  ,但是2大於棧頂的1  ,也就是說 2 是1 後面第一個比他大的數
            //   這是應該將1彈出,2壓入
            // 棧:  3 2
            // 輸入  4          3<4  彈棧(清空棧)  4入棧
            // 棧:  4
           
            //2. 棧底元素大於等於輸入
            if (input[bottom] >= input[i]) {
                // 需要判斷棧頂是否也是比新元素大
                // 棧頂較小,說明新元素是棧頂元素的後面的第一個比他大的元素
                if (input[stack.peek()] < input[i]) {
                    result[stack.pop()] = input[i];
                }
                // 這裏保證了 棧中元素是: 棧底->棧頂 是由大到小的順序
                if (stack.isEmpty()) {
                    bottom = i;// 更新棧底指針
                }
                stack.push(i);
                continue;
            }

            //3. 輸入元素大於棧底,那麼全部彈棧
            while (!stack.isEmpty()) {
                result[stack.pop()] = input[i];
              }
            bottom = i;
            stack.push(i);

        }
        // 4 .處理沒找到之後的比他大的位置,此時索引應該還在棧中
        while (!stack.isEmpty()){
            result[stack.pop()]=Integer.MIN_VALUE;
        }
        return result;


    }

    public static void main(String[] args) {
        int[] input = RandomUtil.randomInts(1, 20, 10);
        RandomUtil.printArray(input);
        System.out.println("------------------------");
       int [] result=new FindFirstBiggerAfterSelf().solution(input);
        RandomUtil.printArray(result);
    }
}

測試:第一行是輸入,分割線後是輸出
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章