4 minute read



입출력 예시

Input-1
[[60, 50], [30, 70], [60, 30], [80, 40]]
Output-1
4000

Input-2
[[10, 7], [12, 3], [8, 15], [14, 7], [5, 15]]
Output-2
120

Input-3
[[14, 4], [19, 6], [6, 16], [18, 7], [7, 11]]
Output-3
133


문제 풀이

주어진 2차원 배열에서 명함의 가로와 세로길이 [w, h]에서 w와 h의 크고 작은 값을 비교해야 한다.
그리고 큰값과 작은값의 최대값을 찾아 곱하면 모든 명함의 길이를 수용할 수 있는 최소의 크기를 구할 수 있다.

내가 생각한 아이디어는 아래와 같다.

  • w의 합과 h의 합을 구한다.
  • 만약 w의 합이 h의 합보다 더 크다면, w가 h보다 작을 때 w와 h값을 치환한다.
  • 만약 h의 합이 w의 합보다 더 크다면, h가 w보다 작을 때 w와 h값을 치환한다.
  • w와 h의 최대값을 구해 곱한다.

한 번 코드로 작성해보자.
먼저 w와 h의 합을 저장할 변수를 초기화한다.

1
2
int w_sum = 0;
int h_sum = 0;


그리고 sizes 2차원 배열을 순회하며 w와 h의 합을 구한다.

1
2
3
4
for(int i=0; i<sizes.length; i++) {
    w_sum += sizes[i][0];
    h_sum += sizes[i][1];
}


w합과 h합을 구했으니, 둘의 크고 작음을 확인하여 w와 h를 치환한다.
w합이 h홥보다 크면, w로 큰 값을 몰아줘야 하니, w값이 작을 때만 치환하면 된다.
반대로, h합이 w합보다 크면, h로 큰 값을 몰아줘야 하기에 h값이 작을 때만 치환한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if(w_sum > h_sum) { // w합이 h보다 클 경우
    for(int i=0; i<sizes.length; i++) {
        int temp = 0;
        if(sizes[i][0] < sizes[i][1]) { // w<h 일 때 치환
            temp = sizes[i][0];
            sizes[i][0] = sizes[i][1];
            sizes[i][1] = temp;
        }
    }
}
else { // h합이 w합보다 클 경우
    for(int i=0; i<sizes.length; i++) {
        int temp = 0;
        if(sizes[i][0] > sizes[i][1]) { // h<w 일 때 치환
            temp = sizes[i][0];
            sizes[i][0] = sizes[i][1];
            sizes[i][1] = temp;
        }
    }
}


마지막으로 치환된 sizes 배열에서 w와 h의 최대값을 찾아 곰하여 반환하면 된다.

1
2
3
4
5
6
7
int w_max = sizes[0][0]; // width 최대값
int h_max = sizes[0][1]; // height 최대값
for(int i=0; i<sizes.length; i++) {
    if(w_max < sizes[i][0]) w_max = sizes[i][0];
    if(h_max < sizes[i][1]) h_max = sizes[i][1];
}
int answer = w_max * h_max; // 최소 명함의 크기

제출하니 정상적으로 모든 테스트케이스를 통과하였다.

코드 수정

그런데, 위에서 작성한 코드가 생각보다 가독성이 좋지 않다고 느꼈고, 간결하면서 가독성이 좋은 코드로 고쳐보려 한다.
다시 생각해본 아이디어는 아래와 같다.

  • 반복문을 돌며 w와 h의 크고 작은 값을 구한다.
  • w와 h가 클 때의 최대값과 작을 때의 최대값을 함께 구한다.

위와 같은 아이디어로 구상하면 하나의 반복문 내에서 간단한 로직으로 구현할 수 있게 된다.
그러면 코드로 작성해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int big = 0;
int sml = 0;

for(int[] size : sizes) {
    if(size[0] < size[1]) {
        big = Math.max(size[1], big);
        sml = Math.max(size[0], sml);
    }
    else {
        big = Math.max(size[0], big);
        sml = Math.max(size[1], sml);
    }
}

return big * sml;

위 코드를 보면 앞에서 작성한 코드보다 훨씬 간결하고 가독성이 좋아졌음을 알 수 있다.
반복문 내에서 w가 h보다 작다면, big에 h가 큰 값을, sml에 w가 작은 값을 저장해나간다.
반대로, w가 h보다 크다면, big에 w가 큰 값을, sml에 h가 작은 값을 저장해나간다.
그렇게 w와 h의 크고 작은 값들의 최대값을 추려낼 수 있다.

고친 코드도 제출해보니 모든 테스트케이스를 정상적으로 통과하였다.


작성 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import java.util.*;

class Solution {
    public static void main(String[] args) {
        
        // int[][] sizes = {{10,7},{12,3},{8,15},{14,7},{5,15}};
        // int[][] sizes = {{14,4},{19,6},{6,16},{18,7},{7,11}};
        int[][] sizes = {{60,50},{30,70},{60,30},{80,40}};
        

        long start = System.currentTimeMillis();
        solution2(sizes);
        long end = System.currentTimeMillis();
        System.out.println("\n수행시간 = " + (end-start));
    }
    public static int solution(int[][] sizes) {
        int w_sum = 0;
        int h_sum = 0;
        
        for(int i=0; i<sizes.length; i++) {
            w_sum += sizes[i][0];
            h_sum += sizes[i][1];
        }

        if(w_sum > h_sum) {
            for(int i=0; i<sizes.length; i++) {
                int temp = 0;
                if(sizes[i][0] < sizes[i][1]) {
                    temp = sizes[i][0];
                    sizes[i][0] = sizes[i][1];
                    sizes[i][1] = temp;
                }
            }
        }
        else {
            for(int i=0; i<sizes.length; i++) {
                int temp = 0;
                if(sizes[i][0] > sizes[i][1]) {
                    temp = sizes[i][0];
                    sizes[i][0] = sizes[i][1];
                    sizes[i][1] = temp;
                }
            }
        }

        int w_max = sizes[0][0];
        int h_max = sizes[0][1];
        for(int i=0; i<sizes.length; i++) {
            if(w_max < sizes[i][0]) w_max = sizes[i][0];
            if(h_max < sizes[i][1]) h_max = sizes[i][1];
        }
        int answer = w_max * h_max;
        return answer;
    }

    public static int solution2(int[][] sizes) {
        int big = 0;
        int sml = 0;

        for(int[] size : sizes) {
            if(size[0] < size[1]) {
                big = Math.max(size[1], big);
                sml = Math.max(size[0], sml);
            }
            else {
                big = Math.max(size[0], big);
                sml = Math.max(size[1], sml);
            }
        }

        return big * sml;
    }
}

회고

  • 알고리즘 문제 정답에 수렴하는 아이디어도 중요하지만, 아이디어를 구상하는 과정에서 더 나은 코드를 위해 고민하였고, 간결하고 가독성 좋은 코드를 작성할 수 있었다.