Determine whether two lines would intersect on a Cartesian plane
EasyUpdated: Sep 13, 2025
Problem
Given two lines on a Cartesian plane, determine whether they intersect. Each line is represented in the form .
Examples
Example 1
Input:
Line 1: 2x + 3y + 4 = 0
Line 2: 4x + 6y + 8 = 0
Output:
True
Explanation:
The lines are the same (they overlap), so they intersect everywhere.
Example 2
Input:
Line 1: x + y + 1 = 0
Line 2: x + y - 2 = 0
Output:
True
Explanation:
The lines are parallel but have different intercepts, so they do not overlap, but they are not the same line. They do not intersect.
Example 3
Input:
Line 1: x + y + 1 = 0
Line 2: x - y + 2 = 0
Output:
True
Explanation:
The lines have different slopes, so they intersect at a single point.
Constraints
- Each line is represented by coefficients , all real numbers.
- Lines may be identical, parallel, or intersecting.
Solution
Method 1 – Slope Comparison
Intuition
Two lines on a Cartesian plane will intersect unless they are parallel and not coincident. The slope of a line is (if ). If the slopes are different, the lines intersect. If the slopes are the same, check if the lines are coincident (identical) or parallel (never meet).
Approach
- For each line, extract coefficients .
- Compute the slope for each line as (handle vertical lines where ).
- If slopes differ, lines intersect at a single point.
- If slopes are the same:
- If the lines are coincident (all coefficients proportional), they overlap (infinite intersection).
- Otherwise, they are parallel and do not intersect.
- Use a small epsilon for floating point comparison.
Code
C++
class Solution {
public:
static constexpr double kEpsilon = 1e-9;
bool Intersect(const std::array<double, 3>& l1, const std::array<double, 3>& l2) {
double a1 = l1[0], b1 = l1[1], c1 = l1[2];
double a2 = l2[0], b2 = l2[1], c2 = l2[2];
// Handle vertical lines
if (std::abs(b1) < kEpsilon && std::abs(b2) < kEpsilon) {
return std::abs(a1 * c2 - a2 * c1) < kEpsilon;
}
double slope1 = (std::abs(b1) < kEpsilon) ? std::numeric_limits<double>::infinity() : -a1 / b1;
double slope2 = (std::abs(b2) < kEpsilon) ? std::numeric_limits<double>::infinity() : -a2 / b2;
if (std::abs(slope1 - slope2) > kEpsilon) return true;
// Check if lines are coincident
double ratio_a = (std::abs(a2) > kEpsilon) ? a1 / a2 : 0;
double ratio_b = (std::abs(b2) > kEpsilon) ? b1 / b2 : 0;
double ratio_c = (std::abs(c2) > kEpsilon) ? c1 / c2 : 0;
return std::abs(ratio_a - ratio_b) < kEpsilon && std::abs(ratio_b - ratio_c) < kEpsilon;
}
};
Go
const epsilon = 1e-9
func Intersect(l1, l2 [3]float64) bool {
a1, b1, c1 := l1[0], l1[1], l1[2]
a2, b2, c2 := l2[0], l2[1], l2[2]
if math.Abs(b1) < epsilon && math.Abs(b2) < epsilon {
return math.Abs(a1*c2 - a2*c1) < epsilon
}
var slope1, slope2 float64
if math.Abs(b1) < epsilon {
slope1 = math.Inf(1)
} else {
slope1 = -a1 / b1
}
if math.Abs(b2) < epsilon {
slope2 = math.Inf(1)
} else {
slope2 = -a2 / b2
}
if math.Abs(slope1-slope2) > epsilon {
return true
}
var ratioA, ratioB, ratioC float64
if math.Abs(a2) > epsilon {
ratioA = a1 / a2
}
if math.Abs(b2) > epsilon {
ratioB = b1 / b2
}
if math.Abs(c2) > epsilon {
ratioC = c1 / c2
}
return math.Abs(ratioA-ratioB) < epsilon && math.Abs(ratioB-ratioC) < epsilon
}
Java
public class Solution {
private static final double EPSILON = 1e-9;
public boolean intersect(double[] l1, double[] l2) {
double a1 = l1[0], b1 = l1[1], c1 = l1[2];
double a2 = l2[0], b2 = l2[1], c2 = l2[2];
if (Math.abs(b1) < EPSILON && Math.abs(b2) < EPSILON) {
return Math.abs(a1 * c2 - a2 * c1) < EPSILON;
}
double slope1 = Math.abs(b1) < EPSILON ? Double.POSITIVE_INFINITY : -a1 / b1;
double slope2 = Math.abs(b2) < EPSILON ? Double.POSITIVE_INFINITY : -a2 / b2;
if (Math.abs(slope1 - slope2) > EPSILON) return true;
double ratioA = Math.abs(a2) > EPSILON ? a1 / a2 : 0;
double ratioB = Math.abs(b2) > EPSILON ? b1 / b2 : 0;
double ratioC = Math.abs(c2) > EPSILON ? c1 / c2 : 0;
return Math.abs(ratioA - ratioB) < EPSILON && Math.abs(ratioB - ratioC) < EPSILON;
}
}
Kotlin
class Solution {
private val epsilon = 1e-9
fun intersect(l1: DoubleArray, l2: DoubleArray): Boolean {
val (a1, b1, c1) = l1
val (a2, b2, c2) = l2
if (Math.abs(b1) < epsilon && Math.abs(b2) < epsilon) {
return Math.abs(a1 * c2 - a2 * c1) < epsilon
}
val slope1 = if (Math.abs(b1) < epsilon) Double.POSITIVE_INFINITY else -a1 / b1
val slope2 = if (Math.abs(b2) < epsilon) Double.POSITIVE_INFINITY else -a2 / b2
if (Math.abs(slope1 - slope2) > epsilon) return true
val ratioA = if (Math.abs(a2) > epsilon) a1 / a2 else 0.0
val ratioB = if (Math.abs(b2) > epsilon) b1 / b2 else 0.0
val ratioC = if (Math.abs(c2) > epsilon) c1 / c2 else 0.0
return Math.abs(ratioA - ratioB) < epsilon && Math.abs(ratioB - ratioC) < epsilon
}
}
Python
from typing import List
class Solution:
def intersect(self, l1: List[float], l2: List[float]) -> bool:
epsilon = 1e-9
a1, b1, c1 = l1
a2, b2, c2 = l2
if abs(b1) < epsilon and abs(b2) < epsilon:
return abs(a1 * c2 - a2 * c1) < epsilon
slope1 = float('inf') if abs(b1) < epsilon else -a1 / b1
slope2 = float('inf') if abs(b2) < epsilon else -a2 / b2
if abs(slope1 - slope2) > epsilon:
return True
ratio_a = a1 / a2 if abs(a2) > epsilon else 0.0
ratio_b = b1 / b2 if abs(b2) > epsilon else 0.0
ratio_c = c1 / c2 if abs(c2) > epsilon else 0.0
return abs(ratio_a - ratio_b) < epsilon and abs(ratio_b - ratio_c) < epsilon
Rust
impl Solution {
pub fn intersect(l1: [f64; 3], l2: [f64; 3]) -> bool {
let epsilon = 1e-9;
let (a1, b1, c1) = (l1[0], l1[1], l1[2]);
let (a2, b2, c2) = (l2[0], l2[1], l2[2]);
if b1.abs() < epsilon && b2.abs() < epsilon {
return (a1 * c2 - a2 * c1).abs() < epsilon;
}
let slope1 = if b1.abs() < epsilon { f64::INFINITY } else { -a1 / b1 };
let slope2 = if b2.abs() < epsilon { f64::INFINITY } else { -a2 / b2 };
if (slope1 - slope2).abs() > epsilon {
return true;
}
let ratio_a = if a2.abs() > epsilon { a1 / a2 } else { 0.0 };
let ratio_b = if b2.abs() > epsilon { b1 / b2 } else { 0.0 };
let ratio_c = if c2.abs() > epsilon { c1 / c2 } else { 0.0 };
(ratio_a - ratio_b).abs() < epsilon && (ratio_b - ratio_c).abs() < epsilon
}
}
TypeScript
class Solution {
intersect(l1: [number, number, number], l2: [number, number, number]): boolean {
const epsilon = 1e-9;
const [a1, b1, c1] = l1;
const [a2, b2, c2] = l2;
if (Math.abs(b1) < epsilon && Math.abs(b2) < epsilon) {
return Math.abs(a1 * c2 - a2 * c1) < epsilon;
}
const slope1 = Math.abs(b1) < epsilon ? Infinity : -a1 / b1;
const slope2 = Math.abs(b2) < epsilon ? Infinity : -a2 / b2;
if (Math.abs(slope1 - slope2) > epsilon) return true;
const ratioA = Math.abs(a2) > epsilon ? a1 / a2 : 0;
const ratioB = Math.abs(b2) > epsilon ? b1 / b2 : 0;
const ratioC = Math.abs(c2) > epsilon ? c1 / c2 : 0;
return Math.abs(ratioA - ratioB) < epsilon && Math.abs(ratioB - ratioC) < epsilon;
}
}
Complexity
- ⏰ Time complexity:
O(1), since all operations are simple arithmetic and comparisons. - 🧺 Space complexity:
O(1), only a constant number of variables are used.