本題重點詳解約瑟夫法,約瑟夫法初看晦澀難懂,博主花了好幾天時間研究左神的解題過程,才逐漸頓悟。相信初頓悟時的歸納總結更能幫助讀者理解約瑟夫法,再回頭去看左神的解題過程,會茅塞頓開!
題目描述
每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。hf作為牛客的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的:首先,讓小朋友們圍成乙個大圈。然後,他隨機指定乙個數m,讓編號為0的小朋友開始報數。每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中,從他的下乙個小朋友開始,繼續0…m-1報數…這樣下去…直到剩下最後乙個小朋友,可以不用表演,並且拿到牛客名貴的「名偵探柯南」典藏版(名額有限哦!!_)。請你試著想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1)
如果沒有小朋友,請返回-1
迴圈鍊錶法:
複雜度o(n * m)
class
pnode
}public
class
solution
temp.next=head;
for(
int i=n;i>
1;i--
) temp.next=head.next;
head=head.next;
}return temp.val;
}}
約瑟夫法:
複雜度o(n)
上述鍊錶法每出列乙個小朋友,都要遍歷m個結點,共n個小朋友就得遍歷n-1次,直到最後剩下的乙個小朋友成為幸運兒.
猜想:那我們是否可以做到不遍歷鍊錶就能知道誰最終將會成為那個幸運兒呢?
思考:當最後只剩下乙個小朋友時,毋庸置疑他即為最終那個幸運兒,可以立馬得出結論其當前編號為0,但我們想知道的是他在最初隊伍中的編號,若我們能由他在i-1個結點中的編號推出他在i個結點中的編號,是不是就能由他在1個結點中的編號不斷地一步步向上推,直到得出他在n個結點中的編號!
解決過程:
1、假設在n個結點中,記小朋友編號為b,報數為a.a
b001
1……n-2
n-2n-1
n-1n
0n+11…
…2n-2
n-22n-1
n-12n
02n+1
1從中我們可以得出a與b的關係:b=a%n(此式不唯一,滿足a與b正確關係即可),由題意:是報數到m-1,則b=(m-1)%n.
注:該假設是作為n個結點情況,結點是從頭以編號0開始,雖說這是一種特殊情況,但其可以上公升至一般情況。在i個結點狀態下,可能結點是從結尾以編號0開始,也可能是從中間以編號0開始,還是可以通過這種方式來計算,我們要得出的只是在i個結點情況下,被刪除結點的編號。
2、假設n個結點的結點順序為old,刪掉乙個結點s後,n-1個結點的結點順序為new.
oldnew…
…s-2
n-3s-1
n-2s
delete
s+10
s+21……
從中我們可以得出new與old的關係:old=(new+s+1)%n(此式不唯一,滿足new與old正確關係即可)
由於s作為old(n個結點)中被刪除的編號,可帶入1中式子b=(m-1)%n至上式,化簡後最終得:old=(new+m)%n.該式只與m,n有關.
注:這是基於刪除某一結點這種特殊情況所得old與new之間關係的特殊式,但其實已上公升至一般式,同樣可適用於:已知new中任意結點編號,即可知在old中該結點所對應的編號。因此,若已知在new中倖存結點編號,即可知在old中該倖存結點所在編號,不斷向上對映,即可獲得在n個結點中倖存結點所在編號。
總結:
到此,我們已經具備了遞迴的兩個條件:
結束條件:n==1時,編號為0;
迴圈體:old與new之間的關係(n個結點時倖存結點編號與n-1個結點時倖存結點編號之間的關係)old=(new+m)%n
自下而上最終獲取n個結點時倖存結點所在編號.
程式如下,數學之美,讓程式變得既簡介,複雜度又低.
public
class
solution
}
孩子們的遊戲 圓圈中最後剩下的數 約瑟夫問題
每年六一兒童節,nowcoder都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。hf作為nowcoder的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的 首先,讓小朋友們圍成乙個大圈。然後,他隨機指定乙個數m,讓編號為0的小朋友開始報數。每次喊到m的那個小朋友要出列唱首歌,然後可以在...
孩子們的遊戲(圓圈中最後剩下的數) 約瑟夫環
每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。hf作為牛客的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的 首先,讓小朋友們圍成乙個大圈。然後,他隨機指定乙個數m,讓編號為0的小朋友開始報數。每次喊到m 1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮...
孩子們的遊戲 圓圈中最後剩下的數
六一兒童節快要到了,牛妹為小夥伴們準備了乙個小遊戲,學會了可以將一堆小盆友馴 調 服 教 成功噢 第一步 你需要準備一堆小禮品,其中乙份一定是所有小盆友都喜歡的,這個你懂噠 第二步 讓小盆友們圍成乙個大圈,你隨機指定乙個數m,讓編號為0的小盆友開始報數 第三步 規定每次喊到m的那個小朋友要出列唱首歌...