題目:0,1,···,n-1這n個數字排成一個圓圈,從數字0開始,每次從這個圓圈裏刪除第m個數字。求出這個圓圈裏剩下的最後一個數字。
解法一:使用LinkedList仿圓就可以了,很簡單
import java.util.*;
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n<=0||m<=0)return -1;
LinkedList<Integer> list = new LinkedList();
for(int i =0;i<n;i++){
list.add(i);
}
int cur = 0;
while(list.size()>1){
cur = (cur+m-1)%list.size();
list.remove(cur);
}
return list.getFirst();
}
}
時間複雜度:O(n)
空間複雜度:O(n)
解法二:使用數學公式遞推
1、首先定義剩下的數:f(n,m)
2、第一個被刪除的數字爲s,由解法一我們可以知道s=(m-1)%n
3、當刪完s以後,剩下的數字爲0,1...,s-1,s+1,...n-2當從k+1處繼續開始數m個數,我們以k+1爲開頭
當前數組排列爲:s+1,s+2, ... 0, 1, ...s-1
對應映射數組爲:0 ,1 , ... n-2-s,n-1-s...,n-2
這裏設映射數字爲x,當前數字爲y。y=(x+s+1)%n
在映射的數組中,因爲我們定義的n個數最後一個數字爲f(n,m),所以在刪除了s之後n-1個數字最後一個數爲f(n-1,m)
把f(n-1,m)轉換成當前數組中的數字即帶入上方公式得:(f(n-1,m)+s+1)%n
4、最終我們有第一步定義的f(n,m) = (f(n-1,m)+s+1)%n,簡化爲:(取餘部分可直接提出,因爲一次跟兩次效果是一樣的)
f(n,m) = (f(n-1,m)+m)%n
當n=1時:f(1,m) = 0
推的是不是很煩!!!看看代碼就高興了,因爲很少,哈哈
import java.util.*;
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if(n<=0||m<=0)return -1;
// 因爲f(1,m) = 0;所以last取0,n從2開始
// 並且f(n,m) = (f(n-1,m)+m)%n所以循環條件i可以=n
int last = 0;
for(int i =2;i<=n;i++){
last = (last+m)%i;
}
return last;
}
}
時間複雜度:O(n)
空間複雜度:O(1)
練習地址:https://www.nowcoder.com/practice/f78a359491e64a50bce2d89cff857eb6