Programmers

[프로그래머스 Level.2] 멀쩡한 사각형 (Summer/Winter Coding(2019)) (Java)

Devtraces 2022. 12. 28. 18:40

문제 링크

https://school.programmers.co.kr/learn/courses/30/lessons/62048

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

 

 

코딩테스트 연습 > Summer/Winter Coding(2019) > 멀쩡한 사각형

 

 

문제 설명

 

 

가로 길이가 Wcm, 세로 길이가 Hcm인 직사각형 종이가 있습니다. 종이에는 가로, 세로 방향과 평행하게 격자 형태로 선이 그어져 있으며, 모든 격자칸은 1cm x 1cm 크기입니다. 이 종이를 격자 선을 따라 1cm × 1cm의 정사각형으로 잘라 사용할 예정이었는데, 누군가가 이 종이를 대각선 꼭지점 2개를 잇는 방향으로 잘라 놓았습니다. 그러므로 현재 직사각형 종이는 크기가 같은 직각삼각형 2개로 나누어진 상태입니다. 새로운 종이를 구할 수 없는 상태이기 때문에, 이 종이에서 원래 종이의 가로, 세로 방향과 평행하게 1cm × 1cm로 잘라 사용할 수 있는 만큼만 사용하기로 하였습니다.


가로의 길이 W와 세로의 길이 H가 주어질 때, 사용할 수 있는 정사각형의 개수를 구하는 solution 함수를 완성해 주세요.

 

 

제한사항
  • W, H : 1억 이하의 자연수

 

 

입출력 예

 

W H result
8 12 80

 

 

 
입출력 예 설명

 

 

입출력 예 #1


가로가 8, 세로가 12인 직사각형을 대각선 방향으로 자르면 총 16개 정사각형을 사용할 수 없게 됩니다. 원래 직사각형에서는 96개의 정사각형을 만들 수 있었으므로, 96 - 16 = 80 을 반환합니다.

 

 

 

 

 

 

나의 코드

class Solution {
    public long solution(int w, int h) {
        long answer = 1;
        
        long width = (long) w;
        long height = (long) h;
        
        long gcdNum = gcd(width, height); // 최대공약수
        
        answer = width * height - (width + height - gcdNum);
        
        return answer;
    }
    
    public long gcd(long w, long h) {
        if(w % h == 0) 
            return h;
        
        return gcd(h, w%h);
    }
}

 

풀이

  1. 이 문제는 규칙을 찾는게 까다로운 문제였다.
  2. 우선 문제에 주어진 직사각형을 봤을 때 가로가 2, 세로가 3일 때 직사각형을 보면 4개가 제외되고 가로가 4, 세로가 6일 때 직사각형을 보면 4*2개가 제외되고 가로가 6, 세로가 9일 때는 4*3개가 제외되고 가로가 8, 세로가 12일 때는 4*4개가 제외되는 것을 볼 수 있다.
  3. 그리고 4, 6의 최대공약수는 2이고 6, 9의 최대공약수는 3이고 8과 12의최대공약수는 4인 것을 봤을 때 종이의 사용할 수 있는 직사각형 수를 구할 규칙을 세워보면 '가로 * 세로 - (4 * 최대공약수)' 로 세울 수 있다.
    여기서 4는 가로 2 세로 3씩 증가하는 직사각형의 패턴에서 볼 수 있는 제외되는 직사각형의 수이므로 직사각형의 패턴에 따라 달라질 수 있다. 그래서 패턴에 따라 제외되는 직사각형의 수를 구하기 위해 몇 가지 직사각형을 만들어 식을 세워보니 '가로 + 세로 - 1'가 나왔다. 문제에 주어진 가로2, 세로3의 직사각형도 2 + 3 - 1 = 4가 되는 것을 볼 수 있다. 이렇게 최종적으로 구한 수식은 '가로 * 세로 - (가로 + 세로 - 1) * 최대공약수' 이다 
  4. 이제 수식을 구했으니 가로, 세로 길이를 통해 최대공약수만 구해서 문제를 풀면 된다.
  5. 최대공약수(gcd)를 구하는 방법은 유클리드 호제법을 이용하면 된다.
    유클리드 호제법은 간단하게 보면 두 개의 자연수 a, b가 있을 때 a를 b로 나눈 나머지를 r이라고 하면 gcd(a, b) = gcd(b, r) 이며, a를 b로 나눈 나머지인 r이 0이면 r이 최대공약수라는 것이다. 이렇게 a를 b로 나눈 나머지 r이 0이 될 때까지 gcd(a, b) = gcd(b, r)를 이용해 recursive 호출을 해서 최대 공약수를 구한다.
  6. 문제에 주어진 w와 h가 1억 이하의 자연수 이므로 위에서 구한 수식을 이용하려면 int의 범위를 벗어날 수 있으므로 long 타입으로 변환하여 구하는 것이 안전하다. 이렇게 long 타입으로 변환한 가로, 세로를 가지고 유클리드 호제법을 이용하여 최대 공약수를 구한 뒤 위의 수식을 적용하여 사용할 수 있는 정사각형의 개수를 구해 리턴 하면 된다.