Problem

Given two coordinates (x1, y1) and (x2, y2), construct the equation of the line that passes through both points.

The line through two distinct points can be written in point-slope form:

1
y - y1 = m (x - x1)

where the slope m = (y2 - y1) / (x2 - x1). For a vertical line (x1 == x2) the equation is x = x1.

Examples

Example 1

1
2
3
Input: (x1,y1) = (3,7), (x2,y2) = (5,11)
Output: y = 2x + 1
Explanation: slope = (11-7)/(5-3) = 2, intercept = 7 - 2*3 = 1

Example 2

1
2
3
Input: (x1,y1) = (2,2), (x2,y2) = (4,12)
Output: y = 5x - 8
Explanation: slope = (12-2)/(4-2) = 5, intercept = 2 - 5*2 = -8

Solution

Method 1 - Point-slope (direct computation)

Intuition

Two distinct points uniquely define a line. Compute the slope m using the two points and substitute into point-slope form to obtain the line equation. If the two points share the same x-coordinate the line is vertical and described by x = c.

Approach

  1. If (x1 == x2) return the vertical line x = x1.
  2. Compute slope m = (y2 - y1) / (x2 - x1) using floating-point arithmetic to handle non-integer slopes.
  3. Compute intercept b = y1 - m * x1.
  4. Return the line as (slope, intercept) or as a formatted equation y = m x + b.
  5. Edge cases:
    • Identical points (x1 == x2 and y1 == y2): the line is undefined (infinite number of lines); treat as a degenerate input — you can return None or indicate the points are identical.

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Solution {
 public:
  struct Point { double x, y; };
  struct Line {
    bool vertical;
    double slope, intercept, x;
    Line(double s, double c): vertical(false), slope(s), intercept(c), x(NAN) {}
    Line(double xv): vertical(true), slope(NAN), intercept(NAN), x(xv) {}
  };

  Line lineFromPoints(const Point& a, const Point& b) {
    const double EPS = 1e-12;
    if (std::abs(a.x - b.x) < EPS && std::abs(a.y - b.y) < EPS) return Line(0.0, 0.0); // identical: degenerate
    if (std::abs(a.x - b.x) < EPS) return Line(a.x); // vertical
    double m = (b.y - a.y) / (b.x - a.x);
    double c = a.y - m * a.x;
    return Line(m, c);
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
type Point struct{ X, Y float64 }
type Line struct{ Vertical bool; Slope, Intercept, X float64 }

func abs(x float64) float64 { if x < 0 { return -x }; return x }

func LineFromPoints(a, b Point) Line {
  const EPS = 1e-12
  if abs(a.X-b.X) < EPS && abs(a.Y-b.Y) < EPS { return Line{false, 0, 0, 0} } // identical
  if abs(a.X-b.X) < EPS { return Line{true, 0, 0, a.X} }
  m := (b.Y - a.Y) / (b.X - a.X)
  c := a.Y - m*a.X
  return Line{false, m, c, 0}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    static final double EPS = 1e-12;

    static class Point { final double x, y; Point(double x, double y) { this.x = x; this.y = y; } }

    static class Line {
        final boolean vertical;
        final double slope, intercept, x;
        Line(double slope, double intercept) { this.vertical = false; this.slope = slope; this.intercept = intercept; this.x = Double.NaN; }
        Line(double x) { this.vertical = true; this.slope = Double.NaN; this.intercept = Double.NaN; this.x = x; }
    }

    public Line lineFromPoints(Point a, Point b) {
        if (Math.abs(a.x - b.x) < EPS && Math.abs(a.y - b.y) < EPS) return null; // identical points
        if (Math.abs(a.x - b.x) < EPS) return new Line(a.x); // vertical
        double m = (b.y - a.y) / (b.x - a.x);
        double c = a.y - m * a.x;
        return new Line(m, c);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
data class Point(val x: Double, val y: Double)

class Solution {
  data class Line(val vertical: Boolean, val slope: Double, val intercept: Double, val x: Double)

  fun lineFromPoints(a: Point, b: Point): Line? {
    val eps = 1e-12
    if (kotlin.math.abs(a.x - b.x) < eps && kotlin.math.abs(a.y - b.y) < eps) return null
    if (kotlin.math.abs(a.x - b.x) < eps) return Line(true, Double.NaN, Double.NaN, a.x)
    val m = (b.y - a.y) / (b.x - a.x)
    val c = a.y - m * a.x
    return Line(false, m, c, Double.NaN)
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Solution:
  def line_from_points(self, a: tuple[float, float], b: tuple[float, float]) -> tuple[float, float] | tuple[str, float] | None:
    EPS = 1e-12
    x1, y1 = a
    x2, y2 = b
    if abs(x1 - x2) < EPS and abs(y1 - y2) < EPS:
      return None
    if abs(x1 - x2) < EPS:
      return ("vertical", x1)
    m = (y2 - y1) / (x2 - x1)
    c = y1 - m * x1
    return (m, c)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
struct Point { x: f64, y: f64 }
struct Line { vertical: bool, slope: f64, intercept: f64, x: f64 }

fn line_from_points(a: &Point, b: &Point) -> Option<Line> {
  let eps = 1e-12;
  if (a.x - b.x).abs() < eps && (a.y - b.y).abs() < eps { return None; }
  if (a.x - b.x).abs() < eps { return Some(Line { vertical: true, slope: f64::NAN, intercept: f64::NAN, x: a.x }); }
  let m = (b.y - a.y) / (b.x - a.x);
  let c = a.y - m * a.x;
  Some(Line { vertical: false, slope: m, intercept: c, x: f64::NAN })
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
type Point = { x: number; y: number };
type Line = { vertical: boolean; slope?: number; intercept?: number; x?: number } | null;

function lineFromPoints(a: Point, b: Point): Line {
  const EPS = 1e-12;
  const abs = (v: number) => (v < 0 ? -v : v);
  if (abs(a.x - b.x) < EPS && abs(a.y - b.y) < EPS) return null;
  if (abs(a.x - b.x) < EPS) return { vertical: true, x: a.x };
  const m = (b.y - a.y) / (b.x - a.x);
  const c = a.y - m * a.x;
  return { vertical: false, slope: m, intercept: c };
}

Complexity

  • ⏰ Time complexity: O(1) — Constant work to compute slope and intercept.
  • 🧺 Space complexity: O(1) — Constant extra space for result and temporaries.