演算法 蓄水問題

2022-07-12 17:54:15 字數 1634 閱讀 5104

問題:    

給定乙個陣列,想象成乙個桶。問最多能裝多少水?

例【1,5,3,6】 最多裝2格水

oo ~ o

o ~ o

o o o

o o o

o o o o

解題思路:

我們把每一列當成一塊板,根據分析,第一塊板和最後一塊板一定不能蓄水,所以問題變成了所有板所能蓄水最大值的總和。先明確這個思路,之後再想辦法。

那麼如何確定當前板可以蓄多少水呢?和它左右兩邊最長的板有關係。等於左右兩邊最長板的較小者減去當前板的長度和0取最大值。

表示為:

當前板蓄水量 = math.max(0, math.min(左最長板,右最長板) - 當前)

第一、最後一塊板蓄水量 = 0

方法一:o(n^2)

簡單暴力,挨個遍歷每一塊板,求出左右最大值,根據上面公式進行計算。不做演示

方法二:o(n)

根據方法一可知,時間複雜度主要在尋找每一塊板的左右最大值。那麼優化的方向就是使用o(n)複雜度獲得每一塊板的左右最大值。

怎麼做呢?借助輔助陣列。

例如【1,5,3,6】,則左邊最大值陣列為【1,5,5,6】,右邊最大值陣列為【6,6,6,6】

三個陣列分別表示當前板長度,當前板的左邊板最大長度、當前板的右邊板最大長度。

public

static

int shui(int

param)

for(int i=param.length - 2;i>0;i--)

int shui = 0;

for(int i = 1; i)

return

shui;

}

方法三:o(n)

方法二空間複雜度太大,所以還有優化空間。

可以從兩邊同時進行判斷,並且儲存當前左右最大值。

如果左邊最大值小於右邊最大值,那麼左邊的當前板所能蓄水量就可確定 = math.max(0, 左最大值 - 當前)。並且當前索引++,標記左邊最大值 = math.max(左最大值,當前板)。

如果右邊最大值小於左邊最大值,那麼右邊的當前板所能蓄水量就可確定 =

math.max(0, 右最大值 - 當前)。並且當前索引--,標記右邊最大值 = math.max(右最大值,當前板)。

如果相等,隨便歸屬一邊,或兩邊一起計算。

/*

* 給定乙個陣列,想象成乙個桶。問最多能裝多少水

* 例【1,5,3,6】 最多裝2格水

* o

* o ~ o

* o ~ o

* o o o

* o o o

* o o o o

* */public

static

int shui(int

param)

else

}return

shui;

}public

static

void

main(string args) ;

system.out.println(shui(a));

}

蓄水池演算法

參考文章 問題定義 給你乙個長度為n的鍊錶。n很大,但你不知道n有多大。你的任務是從這n個元素中隨機取出k個元素。你只能遍歷這個鍊錶一次。你的演算法必須保證取出的元素恰好有k個,且它們是完全隨機的 出現概率均等 求解蓄水池抽樣演算法 該演算法是針對從乙個序列中隨機抽取不重複的k個數,保證每個數被抽取...

蓄水池演算法

適用情況 從n個數中等概率隨機取出k個數,n很大,k也很大 n不固定增量型 內容 當i屬於1 k i入池 當i k i以概率k i決定是否進入池,1 k概率剔除池中乙個數 證明 1 當i 當k個數時,i留下概率 1 當k 1個數時,i被淘汰的概率 1 k k k 1 1 k 1 i留下概率 1 1 ...

蓄水池演算法

在乙個未知的池子裡選1個數字,讓他們被選擇概率一致。假設n的時候,前n個數字被選擇的概率都是1n 當為n 1時候,當前n 1這個數,我們選擇的概率是1n 1,其餘數字的概率是nn 1,那麼一共有n個數字的概率是1n 所以 n 1n 1 n 1 1n 1 具體演算法 使用的方式是i random.ra...