题目
列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法:
从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。
重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。
不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
给你整数 n ,返回 arr 最后剩下的数字。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/elimination-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码
class Solution {
public int lastRemaining(int n) {
int start=1;
int step=1;//隔几个跳步
boolean lTor =true;//判断左右遍历方向
while (n>1){
if (lTor){//从左往右,那么start必定变化
start+=step;
}else {//右往左移,若是奇数,start则变化,偶数不变
if (n%2==1){
start+=step;
}else {
}
}
step*=2;//步长每次翻倍
n/=2;//长度每次减少一半
lTor=!lTor;//顺序每次相反
}
return start;
}
}
要点
- 本题如果模拟删除的话复杂度很高,需要观察规律找出答案
- 仔细分析最终的胜者,发现返回的总是未删除的第一个元素,记为start
- 我们记录start为第一个元素,当顺序删除时,start会右移
- 逆序删除时,若此时长度为奇数,则start会右移,若是偶数,则start不变
- 那么每次右移的长度step也需要分析,结果是没删一轮,step=step*2
- 长度每次减少一半,若只剩一个,那就是答案,此时该元素就是start