leetcode 390. 消除游戏
给定一个从1 到 n 排序的整数列表。
首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾。
第二步,在剩下的数字中,从右到左,从倒数第一个数字开始,每隔一个数字进行删除,直到列表开头。
我们不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
返回长度为 n 的列表中,最后剩下的数字。
示例:
输入:
n = 9,
1 2 3 4 5 6 7 8 9
2 4 6 8
2 6
6
输出:
6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/elimination-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1:传入的参数是n,每次都山区掉 n/2个数字。
2:若剩余的数字是奇数个,则从左测或者从右侧删除的结果相同。迭代为 n = 2n; 若剩余的数字是偶数个,从右侧删除。迭代为 n = 2n - 1;
3:若从左侧删除,剩余的数列 arr2 是 原来数列 arr 的长度的一半,
例如 原来的数组是 2,4,6,8,10 变成了 4, 8,
4:若从右侧删除,
例如 原来的数组是 2,4,6,8,10,12 变成了 2,6,10,
数组 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20(length = 20)
第一次 2,4,6,8,10,12,14,16,18,20 (length 10, value = 2n)
从左侧删除, 所以上一次的n 用2n 代替,1(2n) = 2n
第二次 2,6,10,14,18 (length 5, value = 4n - 2)
因为上一步的长度 10 是偶数,并且从右侧删除, 所以上一次的n 用2n - 1代替,2(2n - 1)= 4n - 2
第三次 6,14 (length 6, value = 8n - 2)
从左侧删除, 所以上一次的n 用2n 代替,4(2n)- 2 = 8n - 2
第四次 6 (length 1, value = 16n - 10) 因为上一步的长度 2 是偶数,并且从右侧删除, 所以上一次的n 用2n - 1代替,8*(2n - 1) - 2= 16n - 10
以上则为通项公式。
public int lastRemaining(int n) { boolean flag = false; int i = 1; int value = 0; while (n != 1) { if ((n & 1) == 0 && flag) { value = value + i; } n >>= 1; i <<= 1; flag = !flag; } return i - value; }