【LeetCode & 劍指offer刷題】發散思維題3:62 圓圈中最後剩下的數字(約瑟夫環問題)
阿新 • • 發佈:2019-01-06
【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...)
62 圓圈中最後剩下的數字(約瑟夫環問題)
題目描述
每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。HF作為牛客的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的:首先,讓小朋友們圍成一個大圈。然後,他隨機指定一個數m,讓編號為0的小朋友開始報數。每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中,從他的下一個小朋友開始,繼續0...m-1報數....這樣下去....直到剩下最後一個小朋友,可以不用表演,並且拿到牛客名貴的“名偵探柯南”典藏版(名額有限哦!!^_^)。請你試著想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1) 方法一:用陣列模擬過程(也可以用連結串列模擬)此時在0’,1’,…,n-2’上再進行一次K報數的選擇。假設f[n-1]的值已經求得,因此我們可以直接求得當選者的編號s’。 但是,該 編號s’是在n-1個候選人報數時的編號,並不等於n個人時的編號 ,所以我們還需要將s’轉換為對應的s。 通過觀察, s和s’編號相對偏移了K,又因為是在環中,因此得到 s = (s'+K) mod n。 即f[n] = (f[n-1] + k) mod n。 /* 方法二:推出遞推公式(動態規劃) i = 1, res =0 i = 2, res = (0+3)%2 = 1 i = 3, res = (1+3)%3 = 1 i = 4, res = (1+3)%4 = 0 ... O(n),O(1) */ class Solution { public : int LastRemaining_Solution ( int n , int k ) { if ( n < 1 || k < 1 ) return - 1 ; //返回-1表示非法輸入 int last = 0 ; for ( int i = 2 ; i <= n ; i ++) last = ( last + k ) % i ; //i個人時刪除數的索引等於i-1個人時刪除數的索引+k(再對i取餘) return last ; } };