2021.10.29 力扣-每日一题-路径交叉

题目描述:

给你一个整数数组 distance 。

从 X-Y 平面上的点 (0,0) 开始,先向北移动 distance[0] 米,然后向西移动 distance[1] 米,向南移动 distance[2] 米,向东移动 distance[3] 米,持续移动。也就是说,每次移动后你的方位会发生逆时针变化。

判断你所经过的路径是否相交。如果相交,返回 true ;否则,返回 false 。

 

方法一:

class Solution {
public:
    bool isSelfCrossing(vector<int>& distance) {
        //第一阶段,在图形逐渐扩大的过程中,每个图形都可以分为a、b、c、d四种边
        int a = 0, b = 0, c = 0, d = 0;
        int n = distance.size();
        //第二阶段,在图形逐渐缩小的过程中,每个图形都可以分为x、y两种边
        int x = 0, y = 0;
        int index = n;
        //开始第一阶段,图形逐渐扩大
        for (int i = 0; i < n; i++)
        {
            int newlen = distance[i];
            //若新的一条边仍然大于c,就说明还处于第一阶段
            if (newlen > c)
            {
                a = b;
                b = c;
                c = d;
                d = newlen;
            }
            //若新的一条边小于c - a,就判断是否路径交叉,若没有则即将进入第二阶段
            else if (newlen < c - a)
            {
                //若存在下一条边,且其长度小于d,说明不会交叉,进入第二阶段
                if (i + 1 < n && distance[i + 1] < d)
                {
                    x = d;
                    y = newlen;
                    index = i + 1;
                    break;
                }
                //若存在下一条边,且其长度大于等于d,说明不会交叉,进入第二阶段
                else if (i + 1 < n && distance[i + 1] >= d)
                {
                    return true;
                }
            }
            //若新的一条边大于等于c - a,小于等于c,就判断是否路径交叉,若没有则即将进入第二阶段
            else if (newlen >= c - a && newlen <= c)
            {
                //若存在下一条边,且其长度小于d - b,说明不会交叉,进入第二阶段
                if (i + 1 < n && distance[i + 1] < d - b)
                {
                    x = d;
                    y = newlen;
                    index = i + 1;
                    break;
                }
                //若存在下一条边,且其长度大于等于d - b,说明不会交叉,进入第二阶段
                else if (i + 1 < n && distance[i + 1] >= d - b)
                {
                    return true;
                }
            }
        }
        //进入第二阶段,图形逐渐缩小
        for (int i = index; i < n; i++)
        {
            int newlen = distance[i];
            //若新的一条边小于x,说明不会路径交叉
            if (newlen < x)
            {
                x = y;
                y = newlen;
            }
            //若新的一条边大于x,则说明路径交叉了
            else if (newlen >= x)
            {
                return true;
            }
        }
        return false;
    }
};

自己画了好多图,才找到的规律,最后一遍过。

我找出的规律是,若将走过的路径看成一个图形,那么这个图形可以分为两个阶段:第一个阶段图形不断扩大,第二个阶段图像将会不断缩小。什么意思呢?请看下文。

第一阶段

第一阶段的不断扩大,即是每次走的竖线都比前一条竖线更长,每次走的横线也都比前一条横线更长,因此能够保证不会有路径交叉。观察下图可以发现,每个图形都可以分出四种边:a, b, c, d,这说明只要处于第一阶段,不管什么样的图形都可以视为同一个模型,这对解题是很有帮助的。

我在每次遍历时,都将a,b,c,d四条边随图形变化,这样每次读取到的一条新的边newlen,只要判断其大小和c的关系:

①若newlen > c,那么将不会有路径交叉,图形依旧处于第一阶段,继续遍历。

②若newlen < c - a,那么注意将可能有路径交叉,如果newlen的下一条边大于等于d,就会出现路径交叉,否则就进入第二阶段。

③若newlen >= c - a && newlen <= c,如果newlen的下一条边大于等于d - b,就会出现路径交叉,否则就进入第二阶段。

第二阶段 

第二阶段的图形,由于受到限制将会越来越小,即每次走的竖线应该比前一条竖线更短,每次走的横线应该比前一条横线更短。

如下图所示,可以看出,这三个图形以后的每一条边的长度,都应该小于x和y才行,否则就会出现路径交叉,同样,每次遍历时更新x和y的长度,毕竟x和y将会越来越小。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值