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; } } }