求一維數組蓄水數

1、需求

很多程序員在面試的時候,都可能遇到一些邏輯思維/編程題,這樣的題目非常有意思。而且非常考驗程序員的解題技巧和代碼編寫能力。我這兒就曾經遇到過一個。

具體需求看圖

 

2、解題思路

廢話不多數。直接給大家講解思路:

1、先找出整個數組中的最大值。

2、整個數組就被這個最大值給分成了兩個數組。

3、左邊數組,從左往右遍歷,計算每個位置的蓄水數,計算規則是:找到當前位置的左邊蓄水的最大高度,當前位置的蓄水數就等於min(leftMaxHeight, maxHeight) - currentHeight

4、右邊數組,從右往左遍歷,計算每個位置的蓄水數,計算規則是:找到當前位置的右邊蓄水的最大高度,當前位置的蓄水數就等於min(rightMaxHeight, maxHeight) - currentHeight

5、最終把每個位置上的蓄水數加起來即可

 

3、實際代碼實現

package com.aura.funny.water;

/**
 * 作者: 馬中華   https://blog.csdn.net/zhongqi2513
 * 時間: 2019/6/20 10:33
 * 描述:
 *      求出一個一維數組的蓄水數。數組中的每個位置上的值,就是高度,
 *      如果某個值的左右兩邊都有比它高的值,那麼這個位置就可以蓄水。
 *      蓄水的容量 = max(左邊, 右邊) - 當前位置的值
 */
public class WaterArray01 {

  public static void main(String[] args) {

    //   能蓄水的位置和值:        0,1,2,0,0,2,2,0
    int[] waterArray1 = new int[]{4,3,2,5,6,4,4,7};
    int result1 = findTotalWaterStorage(waterArray1);
    System.out.println("蓄水總量爲:" + result1);

    //   能蓄水的位置和值:        0,0,0,3,4,1,4,0,1,2,0,0
    int[] waterArray2 = new int[]{2,1,5,2,1,4,1,7,2,1,3,1};
    int result2 = findTotalWaterStorage(waterArray2);
    System.out.println("蓄水總量爲:" + result2);

    //   能蓄水的位置和值:        0,0,0,3,4,1,4,0,1,2,0,0
    int[] waterArray3 = new int[]{4,1,3,5,3,6,2,1,4,7,2,6,4};
    int result3 = findTotalWaterStorage(waterArray3);
    System.out.println("蓄水總量爲:" + result3);
  }

  /**
   * 整體思路:
   *  先找到最高點,然後分別從左,和 從右 往這個高點遍歷。算出蓄水數
   */
  private static int findTotalWaterStorage(int[] waterArray) {

    int totalWater = 0;

    // 最高點的值
    int maxHeight = waterArray[0];
    // 最高點的位置
    int maxHeightIndex = 0;

    // 找出最高點的位置和值
    for(int i = 1; i<waterArray.length; i++){
      if(maxHeight < waterArray[i]){
        maxHeight = waterArray[i];
        maxHeightIndex = i;
      }
    }

    /**
     * 隱性前提: leftHeight  一定小於或者等於  maxHeight
     * 隱性前提: rightHeight 一定小於或者等於  maxHeight
     */

    // 從左往右掃描
    int leftHeight = waterArray[0];
    for(int i=1; i<maxHeightIndex; i++){
      // 如果當前遍歷的位置是低谷
      if(waterArray[i] < leftHeight){
        totalWater += (leftHeight - waterArray[i]);
      }else{
        // 如果不是低谷,則更換左邊的較高位置
        leftHeight = waterArray[i];
      }
    }

    // 從右往左
    int rightHeight = waterArray[waterArray.length-1];
    for(int i=waterArray.length-2; i>maxHeightIndex; i--){
      // 如果當前遍歷的位置是低谷
      if(waterArray[i] < rightHeight){
        totalWater += (rightHeight - waterArray[i]);
      }else{
        // 如果不是低谷,則更換左邊的較高位置
        rightHeight = waterArray[i];
      }
    }
    return totalWater;
  }
}

這種思路的求解的時間複雜度是:O(N)級別。網上其他的O(N * LogN)級別都不可取

 

4、執行效果

 

大功告成。!!!!

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