描述
你站在一个无穷数轴上的 0
位置。在位置目标上有一个目标
。
在每一个动作中,你可以向左或向右。在第n次移动中(从1开始),你行走n步。
返回到达目的地所需的最小步骤数。
目标
将是一个非零的整数范围[-10^9, 10^9]
。
您在真实的面试中是否遇到过这个题?
是
样例
Example 1:
给出目标= 3
返回2
解释:
在第一步,我们从0到1。
在第二步,我们从1到3。
Example 2:
给出目标= 2
返回3
解释:
在第一步,我们从0到1。
在第二个步骤中,我们从1到-1。
在第三步,从-1到2。
我先用了一个类似于DFS的方法,但是这样做的坏处在于不知道如何判断何处应当停止,稍不留神就会溢出或者是超时。这是我最初的代码,思路是对着的,但是在-1000000000处超时了。
class Solution {
public:
/**
* @param target: the destination
* @return: the minimum number of steps
*/
int reachNumber(int target) {
// Write your code here
if(target<0) target=-target;
int tmp=0;
int i=1;
for(;tmp<target;i++) tmp+=i;
return reach(0,target,i+3);
}
int reach(int n,int target,int max){
if(target==0&&n<max) return n;
else if(n>=max) return max;
n++;
int left=reach(n,target+n,max);
int right=reach(n,target-n,max);
return min(left,right);
}
};
于是换了思路,当成数学题来解决。
分析如下:首先一次相加直到和大于目标,比较差值,如果是偶数,说明只需要将几个数又加号变为减号(里外里2倍,所以一定是偶数),若是奇数,就要想办法制造1,减去一个奇数加上下一个偶数即可,所以如果当前n是个奇数,就需要加上下一个偶数,如果当前是个偶数就需要减去下一个奇数,加上下一个偶数。
class Solution {
public:
/**
* @param target: the destination
* @return: the minimum number of steps
*/
int reachNumber(int target) {
// Write your code here
target = abs(target);
int step = 1, pos = 0;
while (pos < target) {
pos += step;
step++;
}
step--;
if (pos == target) return step;
pos -= target;
if (pos % 2 == 0) {
return step;
} else if ((step + 1) % 2 == 1) {
return step + 1;
} else {
return step + 2;
}
}
};