CSES Solution Line Segment Intersection (original) (raw)
Last Updated : 23 Jul, 2025
There are two line segments: the first goes through the points (x 1, y 1 ) and (x 2 ,y 2 ), and the second goes through the points ****(x** 3 ,y 3 ) and (x 4 ,y 4 ).
Your task is to determine if the line segments intersect, i.e., they have at least one common point.
**Example:
**Input: points = {1, 1}, {5, 3}, {1, 2}, {4, 3}
**Output: No**Input: points = {1, 1}, {5, 3}, {1, 1}, {4, 3}
**Output: No
**Approach:
- The main idea is to use the concept of cross products to determine if the line segments intersect.
- Calculate the **cross products of the vectors **AB and **AC, and **CD and **AB.
- Check if the **cross products have different signs, If the signs of the cross products are different, it means that the line segments intersect.
- Check if any of the **cross products is **zero, then check if the point **C or D lies on the line segment **AB or point **A or **B lies on the line segment **CD. If so, the line segments intersect.
- Return "**YES" if the line segments intersect, and "**NO" otherwise.
Steps-by-step approach:
- Calculate the cross products of **AB and **CD, **AB and **DA, **CD and **AB, and **CD and **BA.
- Check if any of the cross products are **zero and if the corresponding points are midpoints.
- Return true
- Check if the signs of the cross products are different for **AB and **CD, and for **CD and **AB.
- Return true
- Otherwise, Return false
Below are the implementation of the above approach:
C++ `
#include <bits/stdc++.h> using namespace std;
#define int long long #define endl '\n' #define Point complex #define X real() #define Y imag()
// Function to calculate cross product of two vectors AB and AC int crossProduct(Point A, Point B, Point C) { Point AB = B - A; // Vector from A to B Point AC = C - A; // Vector from A to C return (conj(AB) * AC).Y; // Cross product of AB and AC }
// Function to compare two points bool comparePoints(const Point &a, const Point &b) { return (a.X == b.X) ? (a.Y < b.Y) : (a.X < b.X); }
// Function to check if point C lies between point A and B bool isMidPoint(Point A, Point B, Point C) { vector v = {A, B, C}; sort(v.begin(), v.end(), comparePoints); return (v[1] == C); }
// Function to get sign of a number int sign(int x) { return (x > 0) - (x < 0); }
// Function to check if line segments AB and CD intersect bool doIntersect(Point A, Point B, Point C, Point D) { int crossProduct1 = crossProduct(A, B, C); int crossProduct2 = crossProduct(A, B, D); int crossProduct3 = crossProduct(C, D, A); int crossProduct4 = crossProduct(C, D, B); if (crossProduct1 == 0 && isMidPoint(A, B, C)) return true; if (crossProduct2 == 0 && isMidPoint(A, B, D)) return true; if (crossProduct3 == 0 && isMidPoint(C, D, A)) return true; if (crossProduct4 == 0 && isMidPoint(C, D, B)) return true; if (sign(crossProduct1) != sign(crossProduct2) && sign(crossProduct3) != sign(crossProduct4)) return true; return false; }
signed main() { // Hardcoded input vector<vector> points = { {{1, 1}, {5, 3}, {1, 2}, {4, 3}} };
for (auto& point : points) {
Point A = point[0];
Point B = point[1];
Point C = point[2];
Point D = point[3];
cout << (doIntersect(A, B, C, D) ? "YES" : "NO") << endl;
}
return 0;}
Java
/*code by flutterfly / import java.util.;
class Main { // Class to represent complex numbers static class Point { long x, y;
Point(long x, long y) {
this.x = x;
this.y = y;
}
Point subtract(Point p) {
return new Point(this.x - p.x, this.y - p.y);
}
long crossProduct(Point p) {
return this.x * p.y - this.y * p.x;
}
}
// Function to compare two points
static class PointComparator implements Comparator<Point> {
public int compare(Point a, Point b) {
return (a.x == b.x) ? Long.compare(a.y, b.y) : Long.compare(a.x, b.x);
}
}
// Function to check if point C lies between point A and B
static boolean isMidPoint(Point a, Point b, Point c) {
List<Point> points = Arrays.asList(a, b, c);
points.sort(new PointComparator());
return points.get(1).equals(c);
}
// Function to get sign of a number
static int sign(long x) {
return Long.compare(x, 0);
}
// Function to check if line segments AB and CD intersect
static boolean doIntersect(Point a, Point b, Point c, Point d) {
long crossProduct1 = a.subtract(c).crossProduct(b.subtract(c));
long crossProduct2 = a.subtract(c).crossProduct(d.subtract(c));
long crossProduct3 = c.subtract(a).crossProduct(b.subtract(a));
long crossProduct4 = c.subtract(a).crossProduct(d.subtract(a));
if (crossProduct1 == 0 && isMidPoint(a, b, c))
return true;
if (crossProduct2 == 0 && isMidPoint(a, b, d))
return true;
if (crossProduct3 == 0 && isMidPoint(c, d, a))
return true;
if (crossProduct4 == 0 && isMidPoint(c, d, b))
return true;
if (sign(crossProduct1) != sign(crossProduct2) && sign(crossProduct3) != sign(crossProduct4))
return true;
return false;
}
public static void main(String[] args) {
// Hardcoded input
List<List<Point>> points = new ArrayList<>();
points.add(Arrays.asList(new Point(1, 1), new Point(5, 3), new Point(1, 2), new Point(4, 3)));
for (List<Point> point : points) {
Point A = point.get(0);
Point B = point.get(1);
Point C = point.get(2);
Point D = point.get(3);
System.out.println(doIntersect(A, B, C, D) ? "YES" : "NO");
}
}}
C#
//code by flutterfly using System; using System.Collections.Generic;
class MainClass { // Class to represent complex numbers class Point { public long x, y;
public Point(long x, long y)
{
this.x = x;
this.y = y;
}
public Point Subtract(Point p)
{
return new Point(this.x - p.x, this.y - p.y);
}
public long CrossProduct(Point p)
{
return this.x * p.y - this.y * p.x;
}
}
// Function to compare two points
class PointComparator : IComparer<Point>
{
public int Compare(Point a, Point b)
{
return (a.x == b.x) ? a.y.CompareTo(b.y) : a.x.CompareTo(b.x);
}
}
// Function to check if point C lies between point A and B
static bool IsMidPoint(Point a, Point b, Point c)
{
List<Point> points = new List<Point> { a, b, c };
points.Sort(new PointComparator());
return points[1].Equals(c);
}
// Function to get sign of a number
static int Sign(long x)
{
return x.CompareTo(0);
}
// Function to check if line segments AB and CD intersect
static bool DoIntersect(Point a, Point b, Point c, Point d)
{
long crossProduct1 = a.Subtract(c).CrossProduct(b.Subtract(c));
long crossProduct2 = a.Subtract(c).CrossProduct(d.Subtract(c));
long crossProduct3 = c.Subtract(a).CrossProduct(b.Subtract(a));
long crossProduct4 = c.Subtract(a).CrossProduct(d.Subtract(a));
if (crossProduct1 == 0 && IsMidPoint(a, b, c))
return true;
if (crossProduct2 == 0 && IsMidPoint(a, b, d))
return true;
if (crossProduct3 == 0 && IsMidPoint(c, d, a))
return true;
if (crossProduct4 == 0 && IsMidPoint(c, d, b))
return true;
if (Sign(crossProduct1) != Sign(crossProduct2) && Sign(crossProduct3) != Sign(crossProduct4))
return true;
return false;
}
public static void Main(string[] args)
{
// Hardcoded input
List<List<Point>> points = new List<List<Point>>();
points.Add(new List<Point> { new Point(1, 1), new Point(5, 3), new Point(1, 2), new Point(4, 3) });
foreach (List<Point> point in points)
{
Point A = point[0];
Point B = point[1];
Point C = point[2];
Point D = point[3];
Console.WriteLine(DoIntersect(A, B, C, D) ? "YES" : "NO");
}
}}
JavaScript
// Function to calculate cross product of two vectors AB and AC function crossProduct(A, B, C) { let AB = { X: B.X - A.X, Y: B.Y - A.Y }; // Vector from A to B let AC = { X: C.X - A.X, Y: C.Y - A.Y }; // Vector from A to C return AB.X * AC.Y - AB.Y * AC.X; // Cross product of AB and AC }
// Function to compare two points function comparePoints(a, b) { return (a.X === b.X) ? (a.Y < b.Y) : (a.X < b.X); }
// Function to check if point C lies between point A and B function isMidPoint(A, B, C) { let v = [A, B, C]; v.sort(comparePoints); return (v[1] === C); }
// Function to get sign of a number function sign(x) { return (x > 0) - (x < 0); }
// Function to check if line segments AB and CD intersect function doIntersect(A, B, C, D) { let crossProduct1 = crossProduct(A, B, C); let crossProduct2 = crossProduct(A, B, D); let crossProduct3 = crossProduct(C, D, A); let crossProduct4 = crossProduct(C, D, B); if (crossProduct1 === 0 && isMidPoint(A, B, C)) return true; if (crossProduct2 === 0 && isMidPoint(A, B, D)) return true; if (crossProduct3 === 0 && isMidPoint(C, D, A)) return true; if (crossProduct4 === 0 && isMidPoint(C, D, B)) return true; if (sign(crossProduct1) !== sign(crossProduct2) && sign(crossProduct3) !== sign(crossProduct4)) return true; return false; }
// Hardcoded input let points = [ [{ X: 1, Y: 1 }, { X: 5, Y: 3 }, { X: 1, Y: 2 }, { X: 4, Y: 3 }] ];
for (let point of points) { let A = point[0]; let B = point[1]; let C = point[2]; let D = point[3]; console.log(doIntersect(A, B, C, D) ? "YES" : "NO"); }
Python3
code by flutterfly
import cmath
Function to calculate cross product of two vectors AB and AC
def cross_product(A, B, C): AB = B - A # Vector from A to B AC = C - A # Vector from A to C return AB.conjugate() * AC # Cross product of AB and AC
Function to compare two points
def compare_points(a, b): return (a.real == b.real and a.imag < b.imag) or a.real < b.real
Function to check if point C lies between point A and B
def is_mid_point(A, B, C): v = [A, B, C] v.sort(key=lambda x: (x.real, x.imag)) return v[1] == C
Function to get sign of a number
def sign(x): return (x > 0) - (x < 0)
Function to check if line segments AB and CD intersect
def do_intersect(A, B, C, D): cross_product1 = cross_product(A, B, C) cross_product2 = cross_product(A, B, D) cross_product3 = cross_product(C, D, A) cross_product4 = cross_product(C, D, B) if cross_product1.imag == 0 and is_mid_point(A, B, C): return True if cross_product2.imag == 0 and is_mid_point(A, B, D): return True if cross_product3.imag == 0 and is_mid_point(C, D, A): return True if cross_product4.imag == 0 and is_mid_point(C, D, B): return True if sign(cross_product1.imag) != sign(cross_product2.imag) and sign(cross_product3.imag) != sign(cross_product4.imag): return True return False
Hardcoded input
points = [ [complex(1, 1), complex(5, 3), complex(1, 2), complex(4, 3)] ]
for point in points: A, B, C, D = point print("YES" if do_intersect(A, B, C, D) else "NO")
`
**Time complexity: O(n log n).
**Auxiliary Space: O(1)