單連結串列和之戀和海枯石爛題之分析
兩個單連結串列(singly linked list),每一個節點裡面一個0-9的數字,輸入就相當於兩個大數了。然後返回這兩個數的和(一個新list)。這兩個輸入的list長度相等。
要求是:
- 不用遞迴;
- 要求演算法在最好的情況下,只遍歷兩個list一次 ,最差的情況下兩遍。
關於海枯石爛的分析:
原題:兩個玩家,一堆石頭,假設多於100塊,兩人依次拿,最後拿光者贏,規則是:
- 第一個人不能一次拿光所有的;
- 第一次拿了之後, 每人每次最多隻能拿對方前一次拿的數目的兩倍。求先拿者必勝策略, 如果有的話。怎麼證明必勝。
分析:
這是斐波那契博弈,當且僅當石頭個數是斐波那契數的時候先手必敗。
讓我們用第二數學歸納法證明:
為了方便,我們將 n
記為 f[i]
。
1、當 i=2
時,因為不能全部去完,先手只能取1顆,顯然必敗,結論成立。
2、假設當 i<=k
時,結論成立。
則當 i=k+1
時,f[i] = f[k]+f[k-1]
。
則我們可以把這一堆石子看成兩堆,簡稱 k
堆和 k-1
堆。
(一定可以看成兩堆,因為假如先手第一次取的石子數大於或等於f[k-1]
,則後手可以直接取完 f[k]
,因為 f[k] < 2*f[k-1]
)
對於 k-1
堆,由假設可知,不論先手怎樣取,後手總能取到最後一顆。下面我們分析一下後手最後取的石子數 x
的情況。
如果先手第一次取的石子數 y>=f[k-1]/3
,則這小堆所剩的石子數小於 2y
,即後手可以直接取完,此時 x=f[k-1]-y
,則 x<=2/3*f[k-1]
。
我們來比較一下 2/3*f[k-1]
與 1/2*f[k]
的大小。即 4*f[k-1]
與 3*f[k]
的大小,對兩值作差後不難得出,後者大。
所以我們得到,x<1/2*f[k]
。
即後手取完 k-1
堆後,先手不能一下取完 k
堆,所以遊戲規則沒有改變,則由假設可知,對於 k
堆,後手仍能取到最後一顆,所以後手必勝。
即 i=k+1
時,結論依然成立。
那麼,當 n
不是Fibonacci數的時候,情況又是怎樣的呢?
這裡需要藉助“Zeckendorf定理”(齊肯多夫定理):任何正整數可以表示為若干個不連續的Fibonacci數之和。
關於這個定理的證明,感興趣的同學可以在網上搜尋相關資料,這裡不再詳述。
分解的時候,要取儘量大的Fibonacci數。
比如分解85:85在55和89之間,於是可以寫成85=55+30,然後繼續分解30,30在21和34之間,所以可以寫成30=21+9,
依此類推,最後分解成85=55+21+8+1。
則我們可以把 n
寫成 n = f[a1]+f[a2]+……+f[ap]
。(a1>a2>……>ap
)
我們令先手先取完 f[ap]
,即最小的這一堆。由於各個f
之間不連續,則 a(p-1) > ap + 1
,則有 f[a(p-1)] > 2*f[ap]
。即後手只能取 f[a(p-1)]
這一堆,且不能一次取完。
此時後手相當於面臨這個子游戲(只有 f[a(p-1)]
這一堆石子,且後手先取)的必敗態,即先手一定可以取到這一堆的最後一顆石子。
同理可知,對於以後的每一堆,先手都可以取到這一堆的最後一顆石子,從而獲得遊戲的勝利。
參考博文:斐波那契博弈
本文來自微信:待字閨中,6月29日釋出,原創@陳利人 ,歡迎大家繼續關注微信公眾賬號“待字閨中”。
相關文章
- 最多連續數的子集及單連結串列和之戀分析及解答
- 資料結構之陣列和連結串列資料結構陣列
- 資料結構之單連結串列資料結構
- 資料結構之連結串列與陣列(2):單向連結串列上的簡單操作問題資料結構陣列
- 資料結構實驗之連結串列五:單連結串列的拆分資料結構
- 資料結構之連結串列篇(單連結串列的常見操作)資料結構
- 3.2資料結構之指標和連結串列 1748:約瑟夫問題資料結構指標
- JS資料結構第三篇---雙向連結串列和迴圈連結串列之約瑟夫問題JS資料結構
- 手寫單連結串列基礎之增,刪,查!附贈一道連結串列題
- 面試題—資料結構之單連結串列詳述(基本篇)面試題資料結構
- 畫江湖之資料結構【第一話:連結串列】單向連結串列資料結構
- 畫江湖之資料結構 [第一話:連結串列] 單向連結串列資料結構
- 資料結構之連結串列與陣列(1):陣列和連結串列的簡介資料結構陣列
- 連結串列基礎2(超簡單)--單連結串列的插入和刪除
- 012 通過連結串列學習Rust之持久化單連結串列Rust持久化
- 012 透過連結串列學習Rust之持久化單連結串列Rust持久化
- 資料結構之連結串列與陣列(3):單向連結串列上的簡單操作資料結構陣列
- 結構與演算法(03):單向連結串列和雙向連結串列演算法
- 資料結構之「連結串列」資料結構
- 資料結構之連結串列資料結構
- 資料結構之php實現單向連結串列資料結構PHP
- 連結串列-單連結串列實現
- [redis]SDS和連結串列Redis
- 陣列和連結串列陣列
- 指標和連結串列指標
- c/c++ 線性表之單向連結串列C++
- MapReduce矩陣;及快排單連結串列之解答矩陣
- 資料結構和演算法——Go實現單連結串列並且反轉單連結串列資料結構演算法Go
- 資料結構實驗之連結串列七:單連結串列中重複元素的刪除資料結構
- 資料結構練習題(順序表和單連結串列)C++資料結構C++
- 資料結構之單連結串列的建立與刪除資料結構
- 實戰PHP資料結構基礎之單連結串列PHP資料結構
- python 資料結構之單連結串列的實現Python資料結構
- 資料結構實驗之連結串列九:雙向連結串列資料結構
- 資料結構實驗之連結串列二:逆序建立連結串列資料結構
- JavaScript資料結構 之 連結串列JavaScript資料結構
- 資料結構之連結串列【上】資料結構
- 資料結構之連結串列操作資料結構