[算法分析与设计] leetcode 每周一题: 335. Self Crossing

题目链接: 

335. Self Crossing




题目大意:

给定一个数组 x, x 的各项均为正整数,设在原点处开始, x[0] 代表向北移动的距离, 然后, x[1] 代表向西移动的距离, x[2] 代表向南移动的距离, x[3] 代表向东移动的距离, x[4] 代表又一次向北移动的距离 ... 依此类推, 也即, 按逆时针方向逐次移动 ;
写出 空间复杂度为 O(1) 且为 one-pass 的算法, 以判断移动的路径是否存在交叉 ;

例如: 给定数组 [2, 1, 1, 2], 则输出应为: true ;

例如: 给定数组 [1, 2, 3, 4], 则输出应为: false ;

例如: 给定数组 [1, 1, 1, 1], 则输出应为: true ;




解题过程:

(1) 由于题目的要求, 我只能想到 穷举所有的可能导致相交(或不相交)的情况并进行逐一判断 的方案, 而且只能利用有限( O(1) )的信息进行判断而不能持续保存信息, 不过具体需要逐一判断的方案数则确实有可能抽象得尽量少 ;

(2) 显然, 理想的方式是一旦发现有交叉, 即马上返回 true ;

(3) 发现 只有当 移动次数 >= 4 时才有可能发生交叉; 且特定的方向上的移动也只可能在特定的情况下和特定方向上的轨迹产生交叉; 故考虑, 针对 4个方向的各个情况, 分别进行判断 ;

(4) 但是发现逻辑写起来太乱, 又考虑到 移动模式固定不变, 因此可以认为对给定的一次移动 m 来说, 决定其是否与其他边发生交叉的因素与其当前移动方向无关(也即, 可以一直以其当前移动方向作为 "前方") ;

(5) 在前基础上, 又考虑到 对给定的一次移动 m 来说, 其只可能与其之前的特定的轨迹发生交叉, 因为超过一定次数 (n 次, 后发现 n = 6, 且实际上也不需要检测与倒数第 6 个轨迹(的相切)) 之前的轨迹会呈现 "被包围" 状态, 不存在与 当前移动轨迹交叉的可能 ;

(6) 于是考虑直接写死 (代码中, "i - 1" 即表示倒数前一次的移动, "i - 2" 即表示倒数第一次的移动, ... 依此类推 ;




代码如下:

    bool crossLast3Track( vector< int > & x, int trackIndex ) {
        auto i = trackIndex;
        return x[i] >= x[i - 2] && x[i - 1] <= x[i - 3];
    }
    bool crossLast4Track( vector< int > & x, int trackIndex ) {
        auto i = trackIndex;
        if ( i < 4 ) {
            return false;
        }
        return x[i - 1] == x[i - 3] && x[i] >= x[i - 2] - x[i - 4];
    }
    bool crossLast5Track( vector< int > & x, int trackIndex ) {
        auto i = trackIndex;
        if ( i < 5 ) {
            return false;
        }
        return x[i - 2] >= x[i - 4] && x[i] >= x[i - 2] - x[i - 4] &&
               x[i - 1] <= x[i - 3] && x[i - 1] >= x[i - 3] - x[i - 5];
    }

    bool isSelfCrossing( vector< int > & x ) {
        for ( int i = 3; i < x.size(); i++ ) {
            if ( crossLast3Track( x, i ) ||
                 crossLast4Track( x, i ) ||
                 crossLast5Track( x, i ) ) {
                return true;
            }
        }
        return false;
    }



Runtime: 0 ms


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值