题目描述
在一根无限长的数轴上,你站在0的位置。终点在target的位置。
每次你可以选择向左或向右移动。第 n 次移动(从 1 开始),可以走 n 步。
返回到达终点需要的最小移动次数。
示例 1:
输入: target = 3
输出: 2
解释:
第一次移动,从 0 到 1 。
第二次移动,从 1 到 3 。
示例 2:
输入: target = 2
输出: 3
解释:
第一次移动,从 0 到 1 。
第二次移动,从 1 到 -1 。
第三次移动,从 -1 到 2 。
注意:
target是在[-10^9, 10^9]范围中的非零整数。
首先暴力搜索是肯定超时的,因此肯定是有某种技巧在里面的:
这里的移动次数和数字的正负是无关的,因此都用正数来表示,计算第n个时此时1+2+3+…+n>=target,如果前者等于target那么毫无疑问就是n,那么如果前者之和大于target,并且前者减去target为偶数的话,那么也是n,为什么呢?因为如果是偶数,并且这个偶数肯定小于n,那么在其中一步可以向反方向移动一次,比如我向左移动一次和一开始向右移动一次,这样一来一回就差了2,同样的如果是2,一来一回就是4,因此如果二者之差为偶数,也是n
但是如果二者之差是奇数那么就有点复杂了:那么需要判断下一步是奇数还是偶数即n是偶数还是奇数,要往第一步上面去靠,如果n是奇数,那么下一步是偶数,需要到下下一步二者之差才是偶数,偶数的话就是n,那么总共就是n+2,如果n是偶数,n+1是奇数,那么n+1步和target就是偶数,那么就是n+1步
代码
class Solution {
public int reachNumber(int target) {
int count = 0;
target = Math.abs(target);
while ((count*(count + 1)) /2 < target) {
count ++;
}
int tem = (count*(count + 1)) /2 ;
if((count*(count + 1)) /2 == target){
return count;
}
if((tem - target)%2 == 0){
return count;
}
if(count % 2 == 0){
return count+1;
}else {
return count+2;
}
}
}
排名靠前的代码,利用求根公式直接得出n之后采用根运算来判断是否是偶数
class Solution {
public int reachNumber(int target) {
target = Math.abs(target);
int n = (int)Math.ceil((-1.0 + Math.sqrt(1 + 8.0 * target)) / 2);
if ((n * (n + 1) / 2) == target)
return n;
int d = (n * (n + 1) / 2) - target;
if ((d & 1) == 0)
return n;
return (n & 1) > 0 ? n + 2 : n + 1;
}
}