參考鏈結
題目描述
約瑟夫問題是乙個非常著名的趣題,即由n個人坐成一圈,按順時針由1開始給他們編號。然後由第乙個人開始報數,數到m的人出局。現在需要求的是最後乙個出局的人的編號。
給定兩個int n和m,代表遊戲的人數。請返回最後乙個出局的人的編號。保證n和m小於等於1000。
測試樣例:
5 3返回:4
主要思路
**如下
//遞迴實現
class joseph
return lastincycle(n, m) + 1;
}int lastincycle(int n, int m)
return (lastincycle(n - 1, m) + m) % n;
}};//迭代逆推實現
public int getresult(int n, int m)
int last = 0;
if(n == 1)
for(int i = 2; i <= n; i++)
return last+1;//注意編號是1-n編號的,而演算法是從0~n-1排序的
}
題目描述
約瑟夫問題是乙個著名的趣題。這裡我們稍稍修改一下規則。有n個人站成一列。並從頭到尾給他們編號,第乙個人編號為1。然後從頭開始報數,第一輪依次報1,2,1,2…然後報到2的人出局。接著第二輪再從上一輪最後乙個報數的人開始依次報1,2,3,1,2,3…報到2,3的人出局。以此類推直到剩下以後乙個人。現在需要求的即是這個人的編號。
給定乙個int n,代表遊戲的人數。請返回最後乙個人的編號
測試樣例:
5返回:5
主要思路一(數學推導實現)
**如下
//遞迴實現
class joseph
int result = lastincycle(n, 2);
return result + 1;
}int lastincycle(int n, int m)
int temp = n % m == 0 ? n / m : n / m + 1;
return (lastincycle(temp, m + 1) + temp - 1) % temp * m;
}};
主要思路二(鍊錶實現)
鍊錶實現:參考鏈結
解題思路例子:
由於涉及到頻繁的刪除操作,故資料結構應該選擇鍊錶,這裡選擇linkedlist,其底層實現是迴圈雙鏈表。
每一輪報數完畢之後,將鍊錶尾部節點移動到鍊錶首部,開始新一輪的報數。
鍊錶中僅剩乙個節點,程式結束。
舉個例子:假設n = 24,第乙個人編號為1。
(1)第一輪:依次報1,2,1,2…然後報到2的人出局,則第一輪過後未出局的編號為1、3、5、7、9、11、13、15、17、19、21、23;
(2)第二輪:從上一輪最後乙個報數的人開始依次報1,2,3,1,2,3…報到2,3的人出局。我這裡做的處理是,先將上一輪最後乙個報數的編號移動到最前面,即23、1、3、5、7、9、11、13、15、17、19、21;然後開始第二輪報數,未出局的編號為23、5、11、17;
(3)第三輪:從上一輪最後乙個報數的人開始依次報1,2,3,4,1,2,3,4…報到2,3,4的人出局。同樣,我這裡做的處理是,先將上一輪最後乙個報數的編號移動到最前面,即17、23、5、11;然後開始第三輪報數,未出局的編號為17,此時鍊錶中僅剩乙個節點,故程式結束。
**如下
/**
* 核心資料結構:雙鏈表
*/public int getresult(int n)
while (list.size() > 1)
else
}round++; // 下一輪的最大報數
curr = 0; // 表示還未開始報數
if (list.size() > 1)
}return list.pop();// 返回最後乙個元素
}
演算法題目 約瑟夫環問題
題目 0,1,n 1這n個數字排成乙個圓圈,從數字0開始每次從這個圓圈裡刪除第m個數字。求出這個圓圈裡剩下的最後乙個數字。解法一 經典解法,用環形鍊錶模擬圓圈。這種方法每刪除乙個數字需要m步運算,總共有n個數字,因此總的時間複雜度是o mn 同時這種思路還需要乙個輔助鍊錶來模擬圓圈,其空間複雜度是o...
演算法題目 約瑟夫環問題
題目 0,1,n 1這n個數字排成乙個圓圈,從數字0開始每次從這個圓圈裡刪除第m個數字。求出這個圓圈裡剩下的最後乙個數字。解法一 經典解法,用環形鍊錶模擬圓圈。這種方法每刪除乙個數字需要m步運算,總共有n個數字,因此總的時間複雜度是o mn 同時這種思路還需要乙個輔助鍊錶來模擬圓圈,其空間複雜度是o...
約瑟夫環問題 遞迴推導
題目描述 n個數,編號為 0 1,n 1 排成乙個圓圈,從數字 0 開始,每次從這個圓圈中刪除第 m 個數,請問最後乙個剩下的數是多少?推導過程 定義乙個函式f n,m 為 n 個數中取 m 最後剩下的編號。第乙個被刪除的數是 m 1 n,記為 k 此時因為序列已經不連續,函式可以定義為f n 1,...