传统解法

题目来自 leetcode 335. Self Crossing

题意非常简单,有一个点,一开始位于 (0, 0) 位置,然后有规律地往上,左,下,右方向移动一定的距离,判断是否会相交(self crossing)。

一个很容易想到的方案就是求出所有线段,然后用 O(n^2) 的时间复杂度两两判断线段是否相交,而线段相交的判断,可以列个二元一次方程求解(交点)。这个解法非常容易想到,但是实际操作起来比较复杂,接下去介绍利用向量的解法。

向量解法

简单回顾下向量,具体的自行谷歌。向量就是一条有向线段,这里要用到的是向量的 叉乘。(还有个类似的概念叫做 点积)

叉乘公式:

而因为 p1 X p2 = | a | * | b | * sin α,后者又是平行四边形的面积公式,所以可以用叉乘来求解平行四边形的面积(同理可以求解三角形的面积)。PS:如果给出三个点坐标,求解三角形面积的话,最好用叉乘来做,这样更精确,而不是海伦公式。

向量叉乘还能判断 p0p1 和 p0p2 两个向量, 对于 p0 点而言,p0p1 是位于 p0p2 顺时针方向,还是逆时针方向。

我们回到判断线段相交,两线段相交有如下两种可能。

对于第一种情况,我们可以判断 p1, p2 两点分别位于线段 p3p4 两边,同时满足 p3, p4 两点分别位于线段 p1p2 两边。如何判断?以判断 p1,p2 是否位于线段 p3p4 两边为例,求解叉乘 p3p1 X p3p4,以及 p3p2 X p3p4,如果符合条件,两值必是一正一负。对于第二种情况,因为共线,所以叉乘结果为 0,但是叉乘结果为 0 只能保证共线,并不能保证相交,所以还需要进行如下的判断。

这样解法就呼之欲出了,贡献个判断线段相交的模板:

/**
 * @param {object} a
 * @param {object} b
 * @return {boolean}
 * a, b 表示两条线段。
 * (a.x1, a.y1), (a.x2, a.y2) 分别表示线段 a 两个端点; b 类似
 */

function f(a, b) {

  function online(a, b, c) {
    if (a.x >= Math.min(b.x, c.x) && a.x <= Math.max(b.x, c.x) && a.y >= Math.min(b.y, c.y) && a.y <= Math.max(b.y, c.y))
      return true;

    return false;
  }

  var n1, n2, n3, n4;

  n1 = (a.x1 - b.x2) * (b.y1 - b.y2) - (a.y1 - b.y2) * (b.x1 - b.x2);
  n2 = (a.x2 - b.x2) * (b.y1 - b.y2) - (a.y2 - b.y2) * (b.x1 - b.x2);
  n3 = (b.x1 - a.x2) * (a.y1 - a.y2) - (b.y1 - a.y2) * (a.x1 - a.x2);
  n4 = (b.x2 - a.x2) * (a.y1 - a.y2) - (b.y2 - a.y2) * (a.x1 - a.x2);

  if (n1 * n2 < 0 && n3 * n4 < 0)
    return 1;

  var p1 = {x: a.x1, y: a.y1};

  var p2 = {x: a.x2, y: a.y2};

  var p3 = {x: b.x1, y: b.y1};

  var p4 = {x: b.x2, y: b.y2};

  if (n1 === 0 && online(p1, p3, p4))
    return 1;

  if (n2 === 0 && online(p2, p3, p4))
    return 1;

  if (n3 === 0 && online(p3, p1, p2))
    return 1;

  if (n4 === 0 && online(p4, p1, p2))
    return 1;

  return 0;
}

本题完整代码详见 https://github.com/hanzichi/leetcode/tree/master/Algorithms/Self%20Crossing,求 star, 求 fork,求 follow

还记得高中的向量吗?leetcode 335. Self Crossing(判断线段相交)的更多相关文章

  1. [leetcode]335. Self Crossing

    You are given an array x of n positive numbers. You start at point (,) and moves x[] metres to the n ...

  2. nyoj-1016-德莱联盟(向量叉乘判断线段相交)

    叉乘的坐标表示: A(X1,Y1), B(X2, Y2), C(XC,YC), D(XD, YD);AB = (X2-X1, Y2-Y1);CD = (XD-XC, YD-YC); 向量AB,CD的叉 ...

  3. c#静态构造函数 与 构造函数 你是否还记得?

    构造函数这个概念,在我们刚开始学习编程语言的时候,就被老师一遍一遍的教着.亲,现在你还记得静态构造函数的适用场景吗?如果没有,那么我们一起来复习一下吧. 静态构造函数是在构造函数方法前面添加了stat ...

  4. 《C#编程风格》还记得多少

    开始实习之后,才发现自己是多么地菜.还有好多东西还要去学习. 公司很好,还可以帮你买书.有一天随口问了一下上司D,代码规范上面有什么要求.然后D在Amazon上面找到了这本书<C#编程风格(Th ...

  5. 【编程之外】还记得曾经给'大学导师'写过的报告嘛 --> 前方高能

    写在前面 本文不是讲技术的,也没什么代码可看 本文不是讲技术的,也没什么代码可看 本文不是讲技术的,也没什么代码可看 还记得我们曾经给我们大学''导师''写过的报告嘛? 大学他愿意在凌晨6点向你询问近 ...

  6. c#静态构造函数 与 构造函数 你是否还记得?(转载)

    构造函数这个概念,在我们刚开始学习编程语言的时候,就被老师一遍一遍的教着.亲,现在你还记得静态构造函数的适用场景吗?如果没有,那么我们一起来复习一下吧.静态构造函数是在构造函数方法前面添加了stati ...

  7. 你还记得当初为什么进入IT行业吗?

    说到这个问题,小编相信不少童鞋开始忆往昔峥嵘岁月,那个少年为了心中的改变世界的理想,进入了这个行业,但是呢,有一群人画风就不一样了,他们进入IT行业,完全只是是因为.... 小时候广告看多了....: ...

  8. 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射

    使用Code First建模自引用关系笔记   原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...

  9. .NET成人礼 | 还记得20年前一起拖过的控件吗?

    本文是MVP Ediwang写的回忆一个80后的拖控件的感悟,与君共勉: 每一代人都有记忆里的味道.煤球炉.黑白电视机是属于父母的记忆.而“拖控件”式编程,启蒙了无数像我这样的80后(嗯,89也算80 ...

随机推荐

  1. [整理]PHP/HTML混写的四种方式

    PHP作为一款后端语言,为了输出给浏览器让浏览器呈现出来,无可避免的要输出HTML代码,下文介绍下我用过的三种PHP/HTML混编方法 1.单/双引号包围法 这是最初级的方法了,用法就像下面这样 &l ...

  2. EF Power Tools 数据库逆向生成时T4模板修改

    VS2013上使用EF Power Tools的Reverse Engineer Code First逆向生成. 发现数据库中的decimal(18, 4)字段在生成的mapping类中没有精度和小数 ...

  3. Java查询大文本

    但JAVA本身缺少相应的类库,需要硬编码才能实现结构化文件计算,代码复杂且可读性差,难以实现高效的并行处理. 使用免费的集算器可以弥补这一不足.集算器封装了丰富的结构化文件读写和游标计算函数,书写简单 ...

  4. Python基础之生成器

    1.生成器简介 首先请确信,生成器就是一种迭代器.生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环中.另外,对于生成器的特殊语法支持使得编写一个生成器比 ...

  5. 烂泥:学习Nagios(二):Nagios配置

    本文由秀依林枫提供友情赞助,首发于烂泥行天下 nagios安装完毕后,我们现在就来配置nagios.有关nagios的安装,可以参考<烂泥:学习Nagios(一):Nagios安装>这篇文 ...

  6. windows phpstudy 本地添加自定义域名

    1.本地配置自定义域名访问 2.打开PHPstudy 域名配置 3.打开host.文件地址 C:\Windows\System32\drivers\etc hosts 192.168.1.101 wi ...

  7. corefile 设置

    程序运行的过程中,可能会因为一些隐藏的bug导致崩溃,为了在出问题时,及时记录所在环境的情况,所以要设置core文件的产生.其实其本质就是把进程的内存保存到文件中去. 1.core文件的生成开关和大小 ...

  8. SCCM 客户端的修复

    1. Stopping the SMS Agent Host service (net stop ccmexec) 2. Stopping the WMI service (net stop winm ...

  9. Binary Tree: Write a function to return count of nodes in binary tree which has only one child.

    June 8, 2015 我最喜欢的一道算法题目, 二行代码. 编程序需要很强的逻辑思维, 严密,我还没有很好训练自己.想一想, 二行代码, 五分钟就可以搞定; 最近这几天网上大家热议的 Homebr ...

  10. 洛谷U2641 木板面积(area)——S.B.S.

    题目背景 一年一次的夏令营又要开始了,卡卡西和小伙伴们早就做好了准备,满心期 待着这趟快乐之旅.在一个阳光明媚的清晨,卡卡西在老师的带领下来到了这次 夏令营的首站——“神奇木材加工厂” . 题目描述 ...