You are standing at position 0
on an infinite number line. There is a goal at position target
.
On each move, you can either go left or right. During the n-th move (starting from 1), you take n steps.
Return the minimum number of steps required to reach the destination.
Example 1:
Input: target = 3 Output: 2 Explanation: On the first move we step from 0 to 1. On the second step we step from 1 to 3.
Example 2:
Input: target = 2 Output: 3 Explanation: On the first move we step from 0 to 1. On the second move we step from 1 to -1. On the third move we step from -1 to 2.
心路历程:初看这道题,第一感觉可能的方案有三种:分支限界搜索、DP和数学规律。
先按DP的思路思考,定义d[step][target]表示第step步到达target位置所需要的最小次数(看起来很奇怪)。
那么d[step][target] = d[step - 1][target - step] + 1。此过程中target可能<0,直接取绝对值即可,因为正负仅代表方向,不影响最终结果。按此过程,step最终会等于0,即第0步能到达的位置,当然,d[0][0] = 0,d[0][N] = -1,其中N != 0,-1表示不可达。这样对于DP而言,初值与递推公式都有了,还差边界条件。可以考虑,step最大值为2*target,因为相邻两步方向相反一定会向目标前进一步。比如-1,2,-3,4,....,每2次一定会向前前进一步。
还可以进一步寻找边界,因为如果尽全力向同一个方向搜索,但仍小于target,可以直接认为不可达。例如d[step][target]中,若sum(1+2+...+step) < .target,那么d[step][target] = -1不可达。
所以对可能的step逐个验证即可。这是我的直观想法,还有数学方法,有兴趣的可以看官方答案
class Solution { public int sum(int x){ return (1 + x) * x / 2; } public int reachNumber(int target) { if(target < 0 ) target *= -1; for(int step = 1; step <= 2*target ;step++){ int ans = recurve(step,target); if(ans != -1) return step; } return 2 * target; } public int recurve(int step,int target){ if(target < 0 ) target *= -1; if(step == 0){ if( target == 0) return 0; return -1; } if(sum(step) < target){ return -1; } else if(sum(step) == target){ return step; }else{ int temp = recurve(step-1,Math.abs(target - step)); if(temp == -1) return -1; return temp +1; } } }