海馬汽車:新一代 L3 級智慧電動汽車 7E 將於 2022 年四季度上市
劍指 Offer 62. 圓圈中最後剩下的數字
題目
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
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
題解-連結串列
這道題需要關注的是刪除之後,在圈中的編號變了。後面應該往前移動,這裡可以使用ArrayList不需要我們手動移動元素,我們還是通過索引來刪除的元素。
這題不能用linkedList當成環形連結串列,因為連結串列靠索引找數字需要遍歷會超時。
class Solution { public int lastRemaining(int n, int m) { ArrayList<Integer> list = new ArrayList(); for(int i=0;i<n;i++){ list.add(i); } int pos = 0; int tmp; while(n!=1){ tmp = (pos+m-1)%list.size(); //使用取餘來迴圈操作連結串列 list.remove(tmp); pos = tmp; n--; } return list.get(0); } }
這種暴力解法很容易超時。
題解-數學
只關心最終活著那個人的序號變化
每一輪刪除了一個數字之後,又重新編號 下一個數字為0,重新找m個元素,所以我們需要在編號不斷變化時找到原始的編號。
假設n個數字,刪除第m個數字,最後安全的編號是f(n,m)
每一輪刪除的元素 k = (m-1)%n
k+1 就是新一輪開頭的0,我們需要找到新舊編號之間的聯絡
y代表原來的編號,代表新的編號
y-x = k+1 -> y = k+1+x
注意這裡帶入之後發現應該還要取餘x與y都是大於0的,y = (k+1+x)%n
f(n,m)
= [k+1+f(n-1,m)]%n
= [(m-1)%n+1+f(n-1,m)]%n
最後一個肯定是0,那麼我們用來倒推。
class Solution {
public int lastRemaining(int n, int m) {
int f = 0;
for(int i=2;i<=n;i++){
f= ((m-1)%i+1+f)%i;
}
return f;
}
}