路径交叉哦

路径交叉
问题描述:
给你一个整数数组 distance 。

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

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

解题思路:
1、不管拐多少个弯,不相交的形状最多有两种形状:由内到外、由外到内的螺旋,且一定是向外->向内,向外时判断边界条件,在未超出前边界时转为向内螺旋;根据不同情况确定向内时的边界,超出则说明相交。由于初始没有图形,可以先走几步形成基本轮廓,简化边界条件计算。

2、走完三步时一定不会相交,走完三步时如果在二象限或x轴,则一定开始向内螺旋;如果在第三象限,第四步一定不会相交。走完第四步时,如果在三象限或y轴,则一定开始向内螺旋;如果在四象限,则可以继续向外螺旋。走完4步时,基本外螺旋轮廓已经形成。

3、继续走剩下的,若某一步未超出上一圈的边界,转为向内螺旋计算(这里要注意,以向上走为例,未超出上边界和未到达下边界时形状不同!)
问题求解:

struct pair_hash {
  template <class T1, class T2>
  std::size_t operator()(const std::pair<T1, T2>& p) const {
    auto h1 = std::hash<T1>{}(p.first);
    auto h2 = std::hash<T2>{}(p.second);
    return h1 ^ h2;
  }
};
class Solution {
 public:
  bool isSelfCrossing(vector<int>& distance) {
    unordered_map<pair<int, int>, int, pair_hash> mp;
    int x = 0, y = 0;
    mp[make_pair(0, 0)]++;
    int n = distance.size();
    for (int i = 0; i < n - 1; i++) {
      if (distance[i] < distance[i + 1]) {
        if (i == n - 3) return false;
      } else break;
    }
    for (int i = 0; i < n; i++) {
      if (i % 4 == 0)
        while (distance[i]-- || distance[i] == 0)
          if (!mp[make_pair(x, y + 1)]) mp[make_pair(x, ++y)]++;
          else return true; 
      else if (i % 4 == 1)
        while (distance[i]-- || distance[i] == 0)
          if (!mp[make_pair(x - 1, y)]) mp[make_pair(--x, y)]++;
          else return true;  
      else if (i % 4 == 2)
        while (distance[i]-- || distance[i] == 0)
          if (!mp[make_pair(x, y - 1)]) mp[make_pair(x, --y)]++;
          else return true; 
      else
        while (distance[i]-- || distance[i] == 0)
          if (!mp[make_pair(x + 1, y)]) mp[make_pair(++x, y)]++;
          else return true;  
    }
    return false;
  }
};

问题总结:

先看一下leetcode官方的解释:

我们先通过枚举各种移动方案来归纳路径交叉的规律。

第 11 次移动和第 22 次移动的情况:

因为这两次移动都是各自方向上的第一次移动,所以这两次移动距离将作为之后移动距离的参考系,但本身没有意义。因此,此时只有 2-12−1 一种情况。

第 33 次移动的情况:

此时一定是 2-12−1,第 33 次移动距离相较于第 11 次移动距离,有三种情况:

3-13−1:第 33 次移动距离小于第 11 次移动距离;
3-23−2:第 33 次移动距离等于第 11 次移动距离;
3-33−3:第 33 次移动距离大于第 11 次移动距离。

第 44 次移动的情况:

当前 33 次移动是 3-13−1 时,第 44 次移动距离相较于第 22 次移动距离,有两种情况:

4-14−1:第 44 次移动距离小于第 22 次移动距离;
4-24−2 和 4-34−3:第 44 次移动距离大于等于第 22 次移动距离相同,出现路径交叉。

根据以上结果,我们发现 3-13−1 具有如下性质:如果在当前的第 ii 次移动之后,存在第 jj 次移动(j > ij>i)的距离大于等于第 j-2j−2 次移动的距离,则会出现路径交叉。另外,我们发现 4-14−1 具有和 3-13−1 相同的性质,于是 4-14−1 等价于 3-13−1;不需要继续讨论 4-14−1 的后续情况。

当前 33 次移动是 3-23−2 时,第 44 次移动距离相较于第 22 次移动距离,有两种情况:

4-44−4:第 44 次移动距离小于第 22 次移动距离;
4-54−5 和 4-64−6:第 44 次移动距离大于等于第 22 次移动距离,出现路径交叉。

根据以上结果,我们发现 3-23−2 具有和 3-13−1 相同的性质,于是 4-44−4 等价于 3-23−2,并间接地等价于 3-13−1;不需要继续讨论 4-44−4 的后续情况。

当前 33 次移动是 3-33−3 时,第 44 次移动距离相较于第 22 次移动距离,有三种情况:

4-74−7:第 44 次移动距离小于第 22 次移动距离;
4-84−8:第 44 次移动距离等于第 22 次移动距离;
4-94−9:第 44 次移动距离大于第 22 次移动距离。

根据以上结果,我们发现 4-74−7 也具有和 3-13−1 相同的性质,于是 4-74−7 等价于 3-13−1;不需要继续讨论 4-74−7 的后续情况。

第 55 次移动的情况:

此时还需要讨论前 44 次移动是 4-84−8 或 4-94−9 的情况。

当前 44 次移动是 4-84−8 时,第 55 次移动距离相较于第 33 次移动距离和第 11 次移动距离,有两种情况:

5-15−1:第 55 次移动距离小于第 33 次移动距离减第 11 次移动距离的差;
5-25−2 和 5-35−3:第 55 次移动距离大于等于第 33 次移动距离减第 11 次移动距离的差,出现路径交叉。

根据以上结果,我们发现 5-15−1 也具有和 3-13−1 相同的性质,于是 5-15−1 等价于 3-13−1;不需要继续讨论 5-15−1 的后续情况。

当前 44 次移动是 4-94−9 时,第 55 次移动距离相较于第 33 次移动距离和第 11 次移动距离,有三种情况:

5-45−4:第 55 次移动距离小于第 33 次移动距离减第 11 次移动距离的差;
5-55−5、5-65−6 和 5-75−7:第 55 次移动距离大于等于第 33 次移动距离减第 11 次移动距离的差,且小于等于第 33 次移动距离;
5-85−8:第 55 次移动距离大于第 33 次移动距离。

根据以上结果,我们发现 5-45−4 也具有和 3-13−1 相同的性质,于是 5-15−1 等价于 3-13−1;不需要继续讨论 5-45−4 的后续情况。

第 66 次移动的情况:

此时还需要讨论前 55 次移动是 5-55−5、5-65−6 或 5-75−7 的情况,以及前 55 次移动是 5-85−8 的情况。

当前 55 次移动是 5-55−5、5-65−6 或 5-75−7 时,我们不妨以 5-65−6 为例,第 66 次移动距离相较于第 44 次移动距离和第 22 次移动距离,有两种情况:

6-16−1:第 66 次移动距离小于第 44 次移动距离减第 22 次移动距离的差;
6-26−2 和 6-36−3:第 66 次移动距离大于等于第 44 次移动距离减第 22 次移动距离的差,出现路径交叉。

根据以上结果,我们发现 6-16−1 也具有和 3-13−1 相同的性质,于是 6-16−1 等价于 3-13−1;不需要继续讨论 6-16−1 的后续情况。

当前 55 次移动是 5-85−8 时,第 66 次移动距离相较于第 44 次移动距离和第 22 次移动距离,有三种情况:

6-46−4:第 66 次移动距离小于第 44 次移动距离减第 22 次移动距离的差;
6-56−5、6-66−6 和 6-76−7:第 66 次移动距离大于等于第 44 次移动距离减第 22 次移动距离的差,且小于等于第 44 次移动距离;
6-86−8:第 66 次移动距离大于第 44 次移动距离。

根据以上结果,我们发现 6-46−4 与 5-45−4 的情况类似,都具有 3-13−1 的性质;6-56−5、6-66−6、6-76−7 与 5-55−5、5-65−6、5-75−7 的情况类似,后续可能出现的情况类似于 6-16−1、6-26−2 和 6-36−3;6-86−8 与 5-85−8 的情况类似,后续可能出现的情况类似 6-46−4、6-56−5、6-66−6、6-76−7 和 6-86−8。

至此,我们已经通过归纳基本得到了路径交叉的规律。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/self-crossing/solution/lu-jing-jiao-cha-by-leetcode-solution-dekx/
来源:力扣(LeetCode)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值