传统解法

题目来自 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. ofbiz 本地化及邮件设置126邮箱

    ofibz登陆功能有通过电子邮件找会密码的功能,但找回密码功能需要配置一个发送email的邮箱账号和smtp服务器的配置,具体配置如下: 1:在ofbiz数据库的表product_store_emai ...

  2. jQuery简单入门(五)

    5.Ajax应用 在jQuery中$ajax()方法属于最底层的方法,第二层是load().$.get().$.post(),第三层是$.getScript()和 $.getJSON():下面根据使用 ...

  3. 损失函数(Loss Function)

    转载请注明出自BYRans博客:http://www.cnblogs.com/BYRans/ 线性回归中提到最小二乘损失函数及其相关知识.对于这一部分知识不清楚的同学可以参考上一篇文章<线性回归 ...

  4. (转)android.intent.action.MAIN与android.intent.category.LAUNCHER

    android.intent.action.MAIN决定应用程序最先启动的Activity android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里 在网上看到 ...

  5. MYSQL:使用\G参数改变输出结果集的显示方式

    在mysql命令行工具中执行查询时,当表的列很多的时候显示很乱. 上面的显示你肯定看不清楚吧.以上方式是默认以列(表格)形式显示的.那怎么以行(表单)的方式显示呢,请看下面 OK,搞定. 参考文档:h ...

  6. JavaScript日期控件,用select实现

    <!doctype html> <html> <head> <title>年月日</title> </head> <bod ...

  7. C# ADO.NET编写简单的图书馆管理软件

    使用软件: Microsoft SQL Server 2012 Microsoft Visual Studio 2012 本文地址: http://www.cnblogs.com/go2bed/ 参考 ...

  8. 思科ACI是一种什么样的技术?

    术语: SDN:Software Defined Network,软件定义网络 ACI:Application Centric Infrastracture,以应用为中心的基础网络架构 Fabric: ...

  9. 第9章 用内核对象进行线程同步(1)_事件对象(Event)

    9.1 等待函数 (1)WaitForSingleObject(hObject,dwMilliseonds); ①dwMilliseconds为INFINITE时表示无限等待 ②dwMilliseco ...

  10. MySQL 5.7.x 配置教程

    软件环境 操作系统:windows 10 x64 企业版 MySQL:mysql-5.7.11-winx64 MySQL官网下载:http://downloads.mysql.com/archives ...