算法记录
LeetCode 题目:
列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法:
-
从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。
-
重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。 不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。 给你整数 n ,返回 arr 最后剩下的数字。
说明
一、题目
输入:n = 9
输出:6
解释:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr = [2, 4, 6, 8]
arr = [2, 6]
arr = [6]
二、分析
- 这个题是需要找规律的,[1, n] 之间的数其实是一个等差数列,然后我们间隔一个删掉一个,那么就会将其中的所有奇数全部删掉了,剩下的所有元素都是偶数且会组成一个
步长 * 2、数量 / 2的一个等差数列。 - 这时候如果我们假设首先是第一个元素会被保存下来,那这一轮结束之后他就会加上一个 Step 来跳过被删除的可能。
- 现在进行第二轮删除就要注意情况了,因为前一轮删除时可能最后一个删除是在当前留下队列的后面的,那也就是剩余队列的第一个元素相邻不用删除,但是如果是在留下队列的前面,剩余队列的第一个元素间隔需要删除,以此更新了我们预期留下的值,要么保持不变,要么就是再加上一个新的 Step。
- 以循环迭代,当奇数次删除就第一种情况,偶数次删除就是第二种分情况讨论,直到当前元素个数唯一,就是剩余的那个元素输出即可。
class Solution {
public int lastRemaining(int n) {
int ret = 1, k = 0, step = 1;
while(n > 1) {
if(k % 2 == 0) {
ret += step;
} else {
ret = (n % 2 == 0) ? ret : ret + step;
}
k++;
step <<= 1;
n >>= 1;
}
return ret;
}
}
总结
找规律。