050-二维生物的旅行-754--到达终点数字

第三题 二维生物的旅行

二维生物hip当前处于x轴的0坐标位置,打算去拜访它的老友hop,hop位于坐标轴的target位置。hip有一个很奇怪的能力,其迈出的第n步(从1算起),步长为n。也就是说第一步可以移动的距离为1,第二步可以移动的距离为2,以此类推。每走一步之前,hip都可以决定这一步是向左走还是向右走,但每一步都只能朝一个方向前进。二维生物都很懒,hip希望你能先帮他计算出最少需要走多少步才能到达target位置,他再决定要不要去拜访老友。

输入描述:

每个测试输入包含1个测试用例,即给出目标位置target的值。这里保证-109<=target<=109,且为整数

在一根无限长的数轴上,你站在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]范围中的非零整数。

题解

  • 首先注意到对称性,向正向行走和反向行走相同距离使用最小步数是一样的,因此只考虑target>0的情况。
  • 注意到,走n步所能达到的最大距离为n * (n + 1) / 2。 因此,令a = math.sqrt(2 * target + 0.25) - 0.5,若a == int(a)则说明此时的target正好是a步所能达到的最远距离。直接返回int(a)即可。
  • 如果a != int(a),则将a设置为最远距离大于target的最小步数。此时分情况讨论。
  • 注意到对于走了步数n:
  • 若((n + 1) // 2) % 2 == 1则此时停下来的距离肯定为奇数
  • 若((n + 1) // 2) % 2 == 0则此时停下来的距离肯定为偶数
  • 若步数a对应的奇偶数情况和target正好相同,则输出a。
  • 若步数a对应的奇偶数情况和target不相同,则输出大于a的下一个与target奇偶相同的步数。 直接看代码更清晰
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import math
class Solution(object):
    def reachNumber(self, target):
        """
        :type target: int
        :rtype: int
        """
        if target < 0:
            target = 0 - target
        a = math.sqrt(2 * target + 0.25) - 0.5
        # print(a)
        if a == int(a):
            return int(a)
        else:
            a = int(a) + 1
            if ((a + 1) // 2) % 2 == target % 2:
                return a
            elif a % 2 == 1:
                return a + 2
            else:
                return a + 1