There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number and every other number afterward until you reach the end of the list.算法
Repeat the previous step again, but this time from right to left, remove the right most number and every other number from the remaining numbers.函數
We keep repeating the steps again, alternating left to right and right to left, until a single number remains.this
Find the last number that remains starting with a list of length n.設計
Examplecode
Input: n = 9, 1 2 3 4 5 6 7 8 9 2 4 6 8 2 6 6 Output: 6
首先能夠想到的最原始的一個方法就是構造一個列表,一遍一遍地來回刪除其中的元素,直到列表裏只剩下一個元素。
但這顯然不是問題的設計的初衷。
首先設輸入數據爲 n 時,最終結果爲 f(n).很顯然,有 f(1)=1,f(2)=2.
當 n=2k 時,從1,3,5,... ,2k-1 刪除奇數項後,剩餘的是2,4,6,... ,2k, 共 k 個偶數項。
當 n=2k+1 時,從1,3,5,... ,2k-1 ,2k+1 刪除奇數項後,剩餘的是2,4,6,... ,2k, 共 k 個偶數項。
這兩種狀況在從左到右刪除一遍後,剩下的內容相同,因此最終剩下的一項也相同,因此咱們能夠得出結論:
f(2k+1)=f(2k)遞歸
因此,咱們只需考慮 n 爲偶數的狀況。rem
假設 n=n1=k (k=1,2,3,...)時,f(n1)=m1,那麼當n=n2=2*n1=2k (k=1,2,3,...)時,從左到右第一遍刪除奇數後,還剩下 k 個偶數,此時從右往左刪除,狀況跟n=n1時從左往右開始刪除相似,則最終剩下的是從 2k 往左數第 m1 個偶數,因此f(n2)=n2-2*(m1-1),即:it
f(2k)=2k-2*f(k)+2io
同理,有
f(2^(k+1))=2^(K+1)-2*f(2^k)+2
對上式兩邊同時除以 2^(k+1),有:
f(2^(K+1))/2^(k+1)= - f(2^k)/2^k +1/2^k + 1.
記 g(k)=f(2^k)/2^k,則:
g(k+1)= -g(k)+1/2^k+1.
因爲上式兩邊函數項正負號不一樣,難以推出通項公式,因此咱們須要進一步推理,有:
g(k+1)
= -g(k)+1/2^k+1
= -[-g(k-1)+1/2^(k-1)+1] + 1/2^k +1
= g(k-1)-1/2^k
且有 g(0)=f(1)/1=1, g(1)=f(2)/2=1.
則:
(i) 當 k=2m (m=1,2,3,...) 時,有:
g(2m)
=g(2m-2)-1/2^(2m-1)
=g(2m-4)-1/2^(2m-3)-1/2^(2m-1)
=g(2m-6)-1/2^(2m-5)-1/2^(2m-3)-1/2^(2m-1)
=...
=g(0)-1/2^1-1/2^3-1/2^5-...-1/2^(2m-1)
=1-(2-2/4^m)/3
=(2/4^m+1)/3
當取m=0時,g(2m)=1=g(0),因此,當 k=2m (m=0,1,2,3,...)時,g(2m)=(2/4^m+1)/3
(ii) 當 k=2m+1 (m=1,2,3,...) 時,有:
g(2m+1)
=g(2m-1)-1/2^(2m)
=g(2m-3)-1/2^(2m-2)-1/2^(2m)
=...
=g(1)-1/2^2-1/2^4-1/2^6-...-1/2^(2m)
=1-(1-1/4^m)/3
=(1/4^m+2)/3
當取m=0時,g(2m+1)=1=g(1),因此,當 k=2m+1 (m=0,1,2,3,...)時,g(2m+1)=(1/4^m+2)/3ast
又由於 f(2^k)=2^k*g(k),因此,對於給定的 n ,當 n 爲2^k時,咱們能夠根據k是奇數仍是偶數得出f(n)的公式。即:
(i) 當 n=2^(2m) (m=0,1,2,3,...)時,有:
f(n)
=f(2^(2m))
=2^(2m)*g(2m)
=n*(2/4^m+1)/3
=(n+2)/3
(ii) 當 n=2^(2m+1) (m=0,1,2,3,...)時,有:
f(n)
=2^(2m+1)*g(2m+1)
=n*(1/4^m+2)/3
=(2n+2)/3
因此,對於輸入的 n ,若是是 1,咱們直接返回1 。不然,判斷其是否爲偶數,若是不是,則將其作減1處理,由於 f(2k+1)=f(2k).此時保證n爲偶數。
而後判斷 n 是否爲 2^k,若是是,則根據上面推理出的公式進行計算;若是不是,則遞歸計算 f(n/2) ,由於 f(n)=n-2f(n/2)+2.
代碼以下:
Java算法實現
public class Solution { public int lastRemaining(int n) { if(n==1) return 1; if(n==2) return 2; if((n&0x1)==0x1){ n--;//化爲偶數,由於 f(2k+1)=f(2k) } if(((n-1)&n)==0){ //爲2的整數冪 int index=0; int tmpN=n; tmpN=tmpN>>>1; while(tmpN>0){ //n=2^k,此處用 index 表示k的值 index++; tmpN=tmpN>>>1; } int ans=0; if((index&1)==1){ //index爲奇數 //對應f(n)=(2n+2)/3,此處 tmpN=2n tmpN=n<<1; } else{ //index爲偶數 //對應f(n)=(n+2)/3,此處 tmpN=n tmpN=n; } ans=(tmpN+2)/3; //tmpN=n 或 tmpN=2n return ans; } else{ //n不是2的整數冪,但目前已經能保證n爲偶數,遞歸計算 int tmpAns=lastRemaining(n>>>1); int ans=n-2*tmpAns+2; return ans; } } }