• LeetCode 0754. 到达终点数字


    【LetMeFly】754.到达终点数字

    力扣题目链接:https://leetcode.cn/problems/reach-a-number/

    在一根无限长的数轴上,你站在0的位置。终点在target的位置。

    你可以做一些数量的移动 numMoves :

    • 每次你可以选择向左或向右移动。
    • i 次移动(从  i == 1 开始,到 i == numMoves ),在选择的方向上走 i 步。

    给定整数 target ,返回 到达目标所需的 最小 移动次数(即最小 numMoves

     

    示例 1:

    输入: target = 2
    输出: 3
    解释:
    第一次移动,从 0 到 1 。
    第二次移动,从 1 到 -1 。
    第三次移动,从 -1 到 2 。
    

    示例 2:

    输入: target = 3
    输出: 2
    解释:
    第一次移动,从 0 到 1 。
    第二次移动,从 1 到 3 。
    

     

    提示:

    • -109 <= target <= 109
    • target != 0

    方法一:枚举

    如果 t a r g e t < 0 target<0 target<0,那么我们就对 t a r g e t target target取个绝对值,因为走到 − 100 -100 100 100 100 100所需的步数是一样的

    这样,我们就可以先头也不回地往右走,直到恰好走到 t a r g e t target target或超过 t a r g e t target target一两步为止

    假设我们走了 n n n步,那么总距离就是 r e s u l t = n × ( n + 1 ) 2 result = \frac{n\times(n+1)}{2} result=2n×(n+1)

    我们超过了 t a r g e t target target r e s u l t − t a r g e t result-target resulttarget,因此在这 n n n步中,我们希望有其中某步是往左的。

    假设第 i i i步往左,那么我们 n n n步的总距离就是 r e s u l t − 2 × i result-2\times i result2×i

    也就是说往左一步一直往右少走的距离一定是偶数。

    因此,我们只需要在 r e s u l t ≥ t a r g e t result\geq target resulttarget r e s u l t − t a r g e t result - target resulttarget不为偶数时,不断往右走

    好了,现在我们超过 t a r g e t target target r e s u l t − t a r g e t result-target resulttarget,怎么办呢?我们将往右走的过程中,第 r e s u l t − t a r g e t 2 \frac{result-target}{2} 2resulttarget步改成向左走不就行了么?

    问题解决。

    有的同学可能不相信,那咱就举例说明一下。

    假设目标距离是 2 2 2

    1. 1 = 1 < 2 1 = 1 < 2 1=1<2
    2. 1 + 2 = 3 > 2 1 + 2 = 3 > 2 1+2=3>2,但 ( 1 + 2 ) − 2 = 1 (1+2)-2=1 (1+2)2=1是奇数
    3. 1 + 2 + 3 = 6 > 2 1+2+3=6>2 1+2+3=6>2 ( 1 + 2 + 3 ) − 2 = 4 (1+2+3)-2=4 (1+2+3)2=4是偶数

    因此,我们只需要将第 4 2 = 2 \frac{4}{2}=2 24=2步修改为向左走,总行走距离就变成了 1 − 2 + 3 = 2 1-2+3=2 12+3=2

    这得益于几个条件:

    1. 将target取绝对值后,模板在原点或原点的右边,我们要尽可能地多往右走
    2. 如果一直往右走不能恰好到达 t a r g e t target target,那么就一定要往左走“数次”
    3. “往左一次”只能比“全部往右”少走偶数的距离,这就导致了“把其中某步”改为往左不一定能正好走到 t a r g e t target target
    4. 假设这次超过 t a r g e t target target奇数的距离,那么再往前走一步,一定会超过 t a r g e t target target偶数的距离(这是因为我们是奇偶交替走的,总距离也是奇偶交替的),因此超过 t a r g e t target target后最多再往前走一步,就能“将之前某一步改为向左以恰好达到target”( r e s u l t − t a r g e t 2 \frac{result - target}{2} 2resulttarget一定不大于 n n n

    总之,头也不回地往右走,直到超过 t a r g e t target target偶数的距离(或恰好位于 t a r g e t target target),修改历史某步为向左(不消耗步数),返回当前步数即可

    • 时间复杂度 O ( ∣ t a r g e t ∣ ) O(\sqrt{|target|}) O(target )(注意这里是“根号下target的绝对值”,目前力扣新版UI中无法正常显示\sqrt
    • 空间复杂度 O ( 1 ) O(1) O(1)

    AC代码

    C++
    class Solution {
    public:
        int reachNumber(int target) {
            unsigned to = abs(target);
            unsigned n = 0;
            while (true) {
                unsigned result = n * (n + 1) / 2;
                if (result >= to && (result - to) % 2 == 0)
                    return n;
                n++;
            }
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    方法二:基于方法一的小优化

    方法一中我们从 1 1 1开始“枚举”了步数 n n n找到了 n × ( n + 1 ) 2 ≥ t a r g e t \frac{n\times(n+1)}{2}\geq target 2n×(n+1)target n × ( n + 1 ) 2 − t a r g e t \frac{n\times(n+1)}{2}- target 2n×(n+1)target为偶数的最小 n n n

    这导致时间复杂度为 log ⁡ t a r g e t \log target logtarget

    但是, n × ( n + 1 ) 2 \frac{n\times (n+1)}{2} 2n×(n+1)恰好略大于 t a r g e t target target,这就说明 n n n约等于 t a r g e t × 2 \sqrt{target\times2} target×2

    因此我们从 t a r g e t × 2 − 2 \sqrt{target\times2} - 2 target×2 2开始枚举 n n n就好了,大约不出 5 5 5次就能找到答案。

    • 时间复杂度 O ( 1 ) O(1) O(1)(CPU有专门的计算平方根的指令,aqrt()的复杂度可以视作是 O ( 1 ) O(1) O(1)
    • 空间复杂度 O ( 1 ) O(1) O(1)

    AC代码

    C++
    class Solution {
    public:
        int reachNumber(int target) {
            unsigned to = abs(target);
            unsigned simN = max((int)sqrt(to * 2) - 2, 0);
            while (true) {
                unsigned result = simN * (simN + 1) / 2;
                if (result >= to && (result - to) % 2 == 0)
                    return simN;
                simN++;
            }
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    执行结果确实快了点

    同步发文于CSDN,原创不易,转载请附上原文链接哦~
    Tisfy:https://letmefly.blog.csdn.net/article/details/127684453

  • 相关阅读:
    windows10上使用Visual Studio对树莓派进行交叉编译示例
    使用VMware搭建OceanStor_eStor存储超详细教程
    如何选择最佳视频网站服务器?
    sqlserver查询表中所有字段信息
    access与trunk详细解析+区别
    Tomcat 启动闪退问题解决方法
    思科与华为BGP配置命令对比
    4.1 声明式事务之JdbcTemplate
    【Verilog基础】一些时序约束相关的面试真题
    手把手怎么把照片修复高清,p图小白也能轻松上手
  • 原文地址:https://blog.csdn.net/Tisfy/article/details/127684453