문제 설명

점 네 개의 좌표를 담은 이차원 배열  dots가 다음과 같이 매개변수로 주어집니다.

  • [[x1, y1], [x2, y2], [x3, y3], [x4, y4]]

주어진 네 개의 점을 두 개씩 이었을 때, 두 직선이 평행이 되는 경우가 있으면 1을 없으면 0을 return 하도록 solution 함수를 완성해보세요.

 

제한사항

  • dots의 길이 = 4
  • dots의 원소는 [x, y] 형태이며 x, y는 정수입니다.
    0 ≤ x, y ≤ 100
  • 서로 다른 두개 이상의 점이 겹치는 경우는 없습니다.
  • 두 직선이 겹치는 경우(일치하는 경우)에도 1을 return 해주세요.
  • 임의의 두 점을 이은 직선이 x축 또는 y축과 평행한 경우는 주어지지 않습니다.

 

입출력 예

dots result
[[1, 4], [9, 2], [3, 8], [11, 6]] 1
[[3, 5], [4, 1], [2, 4], [5, 10]] 0

입출력 예 #1 : 점 [1, 4], [3, 8]을 잇고 [9, 2], [11, 6]를 이으면 두 선분은 평행합니다.
입출력 예 #2 : 점을 어떻게 연결해도 평행하지 않습니다.

 

실패 코드

/*
import java.lang.Math;

class Solution {
    public int solution(int[][] dots) {

        int caseX1 = Math.abs(dots[0][0] - dots[1][0]);
        int caseY1 = Math.abs(dots[0][1] - dots[1][1]);
        int case1 = caseY1 / caseX1;
        
        int caseX2 = Math.abs(dots[0][0] - dots[2][0]);
        int caseY2 = Math.abs(dots[0][1] - dots[2][1]);
        int case2 = caseY2 / caseX2;
        
        int caseX3 = Math.abs(dots[0][0] - dots[3][0]);
        int caseY3 = Math.abs(dots[0][1] - dots[3][1]);
        int case3 = caseY3 / caseX3;
        
        int caseX4 = Math.abs(dots[1][0] - dots[2][0]);
        int caseY4 = Math.abs(dots[1][1] - dots[2][1]);
        int case4 = caseY4 / caseX4;
        
        int caseX5 = Math.abs(dots[1][0] - dots[3][0]);
        int caseY5 = Math.abs(dots[1][1] - dots[3][1]);
        int case5 = caseY5 / caseX5;
        
        int caseX6 = Math.abs(dots[2][0] - dots[3][0]);
        int caseY6 = Math.abs(dots[2][1] - dots[3][1]);
        int case6 = caseY6 / caseX6;

        if(case1 == case2) return 1;
        if(case1 == case3) return 1;
        if(case1 == case4) return 1;
        if(case1 == case5) return 1;
        if(case1 == case6) return 1;
        
        if(case2 == case3) return 1;
        if(case2 == case4) return 1;
        if(case2 == case5) return 1;
        if(case2 == case6) return 1;
        
        if(case3 == case4) return 1;
        if(case3 == case5) return 1;
        if(case3 == case6) return 1;
        
        if(case4 == case5) return 1;
        if(case4 == case6) return 1;
        
        if(case5 == case6) return 1;
        
        return 0;

    }
}
*/

코드의 문제점

  1. 절댓값으로 기울기 구하기 → 방향성 무시

    예를 들어 (3,5)와 (4,1)의 기울기를 계산한다고 해보자.

    올바른 기울기: (1 - 5) / (4 - 3) = -4 / 1 = -4

    너의 코드: abs(1 - 5) / abs(4 - 3) = 4 / 1 = 4

    즉, 기울기가 -4인데도 +4로 계산됨 → 기울기 비교가 부정확함

    이로 인해, 실제로는 평행하지 않은 선분들이 기울기가 같다고 잘못 판단됨.

  2. 정수 나눗셈 (int / int)으로 기울기 소수점 정보 손실

    예를 들어 (2, 4)와 (5, 10)을 비교하면:

    기울기: (10 - 4) / (5 - 2) = 6 / 3 = 2.0

    하지만, 만약 (5,10)과 (4,1)처럼 (10 - 1)/(5 - 4) = 9 / 1 = 9라면, 분모가 작을수록 값이 커지게 되므로,
    정수값으로만 기울기를 판단하면 잘못된 결과가 나올 수 있음

 

풀이1

class Solution {
    public int solution(int[][] dots) {
        float[] tmp = new float[6];
        int answer = 0;

        tmp[0] = (float) (dots[0][1] - dots[1][1]) / (dots[0][0] -dots[1][0]);
        tmp[1] = (float) (dots[0][1] - dots[2][1]) / (dots[0][0] -dots[2][0]);
        tmp[2] = (float) (dots[0][1] - dots[3][1]) / (dots[0][0] -dots[3][0]);
        tmp[3] = (float) (dots[1][1] - dots[2][1]) / (dots[1][0] -dots[2][0]);
        tmp[4] = (float) (dots[1][1] - dots[3][1]) / (dots[1][0] -dots[3][0]);
        tmp[5] = (float) (dots[2][1] - dots[3][1]) / (dots[2][0] -dots[3][0]);

        for (int i = 0; i < 6; i++) {
            for (int j = i+1; j < 6; j++) {
                if (tmp[i] == tmp[j]) {
                    answer =1;
                }
            }
        }

        return answer;
    }
}

 

풀이2

class Solution {
    int[][] dots;

    public int solution(int[][] dots) {
        this.dots = dots;
        if (parallel(0, 1, 2, 3)) return 1;
        if (parallel(0, 2, 1, 3)) return 1;
        if (parallel(0, 3, 1, 2)) return 1;
        return 0;
    }

    boolean parallel(int a, int b, int c, int d) {
        int x = (dots[a][0] - dots[b][0]) * (dots[c][1] - dots[d][1]);
        int y = (dots[a][1] - dots[b][1]) * (dots[c][0] - dots[d][0]);
        return x == y || x == -y;
    }
}

왜 세 가지 조합만 비교하면 되는가?

총 네 개의 점이 주어졌을 때, 가능한 선분의 조합은 총 6개지만,
서로 다른 두 선분이 평행한 경우만 찾으면 되기 때문에,
선분 2개를 뽑는 조합(4C2 = 6개) 중, 평행한 두 쌍이 될 수 있는 조합은 단 3가지뿐

네 개의 점이 있다고 하자:

A = dots[0]
B = dots[1]
C = dots[2]
D = dots[3]

세 가지 가능한 "두 쌍의 선분 조합"은:

A-B 와 C-D
A-C 와 B-D
A-D 와 B-C
이 조합 외에는 두 쌍의 선이 완전히 분리되지 않거나 중복돼서 비교할 필요가 없어.

 

곱셈으로 교차 비교하는 이유

기울기 m = (y2 - y1) / (x2 - x1) 이지만, 나눗셈을 사용하면:
- 0으로 나눌 위험
- 소수점 비교 시 오차 발생

 

그래서 대신 사용하는 방식:

(y2 - y1) * (x4 - x3) == (y4 - y3) * (x2 - x1)

→ 두 기울기가 같으면 양변이 같음
이렇게 하면 정수 계산으로도 정확하게 기울기 일치 여부를 알 수 있다.

Developer Quarterly