圓圈中最後剩下的數字
0,1,n-1這n個數字排成一個圓圈,從數字0開始,每次從這個圓圈裏刪除第m個數字。求出這個圓圈裏剩下的最後一個數字。
例如,0、1、2、3、4這5個數字組成一個圓圈,從數字0開始每次刪除第3個數字,則刪除的前4個數字依次是2、0、4、1,因此最後剩下的數字是3。
示例 1:
輸入: n = 5, m = 3
輸出: 3
示例 2:
輸入: n = 10, m = 17
輸出: 2
限制:
1 <= n <= 10^5
1 <= m <= 10^6
思路
1.開始用環形鏈表做,果斷超時。使用list模擬環形鏈表,把數字放入list中,當值超過最右邊時候,通過%當前list長度,達到閉環的作用。
public int lastRemaining(int n, int m) {
ArrayList<Integer> integers = new ArrayList<>();
int index = 0;
//使用list模擬環形鏈表
for (int i = 0; i < n; i++) {
integers.add(i);
}
while (n > 1) {
//需要刪除的數的索引,索引從自身開始計算,所以m-1。
index = (index + m - 1) % n;
n--;
integers.remove(index);
}
return integers.get(0);
}
2.使用動態規劃,從最後一個人往前看,初始狀態是隻剩一人,它的索引爲0,剩兩個人時,它的索引位置爲(m+0)%2,依次往後推,直到剩n個人時,就能求出此時的安全索引位置。
public int lastRemaining(int n, int m) {
int result = 0;
for (int i = 2; i <= n; ++i) {
result = (result + m) % i;
}
return result;
}