LeetCode 记录-754. 到达终点数字

141 阅读2分钟

LeetCode 记录-754. 到达终点数字

我的解法

思路

image.png

记录一下第一个错误的思路:

我发现往后 i 步,再往前 i+1 步,等效于往前 1 步。我就想,先一直往前走,走到第 i 步,使得总步数处于加起来小于 target 且再走第 i+1 步大于 target 的状态。然后剩下的路就是往后一步,再往前一步,一直挪动到 target。但这样步数并不是最小的。

然后是正确解答出问题的思路:

还是先走到上述第 i 步,使得总步数处于加起来小于 target 且再走第 i+1 步大于 target 的状态。继续往前走就会超过 target,设超过的步数为 k。因为考虑到已经超过 target 了,我就想去反走 1 ~ i 步中的一些,这样就可以将超过的部分抵消。假设我们反走了第 j 步,就要在原来的总步数上减去 2j,因为反走等于没有向前走 j(这里要在总步数中减去一次 j),而且向后走 j(这样又要在总步数中减去一次 j)。所以我们只需要继续往前走,使得超过的步数为一个偶数,那么一定可以通过反走前面的,来回到 target。

代码

/**
 * @param {number} target
 * @return {number}
 */
var reachNumber = function (target) {
  const a = 1;
  const b = 1;
  const c = Math.abs(target) * -2;
  const x =
    -1 * ((b / 2) * a) + Math.pow(Math.pow((b / 2) * a, 2) - c / a, 1 / 2);
  if (Number.isInteger(x)) {
    return x;
  }
  let count = Math.floor(x);
  let sum = ((1 + count) * count) / 2;
  count++;
  let rest = sum + count - target;
  while (rest % 2 !== 0) {
    count++;
    rest += count;
  }

  return count;
};

复杂度分析(自我分析,不一定对)

时间复杂度

O(1)O(1),感觉不管输入的 target 多大,计算所需要的时间并不会随着 target 变大而变大。

空间复杂度

O(1)O(1),感觉不管输入的 target 多大,计算所需要的空间也不会随着 target 变大而变大。


官方解法: 分析 + 数学

思路

思路和我第二个差不多,具体请看截图:

image.png

代码

var reachNumber = function (target) {
  target = Math.abs(target);
  let k = 0;
  while (target > 0) {
    k++;
    target -= k;
  }
  return target % 2 === 0 ? k : k + 1 + (k % 2);
};

复杂度分析

时间复杂度

O(target)O(target),循环内最多执行 O(target)次。

使用公式来计算感觉就不需要考虑循环的复杂度,所以我觉得直接使用公式算的时间复杂度还是O(1)O(1),但其实看最终的时间消耗只击败了 75%左右的人,猜测是Math.pow()等函数计算需要额外的时间造成的。

空间复杂度

O(1)O(1),只使用常数空间。