최소직사각형
문제 설명
명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.
아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.
![signcard](https://blog.kakaocdn.net/dn/bm7egZ/btrgFSd4dXY/o0cFpuyu2CDGPltiAk6qU1/img.png)
가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.
모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.
제한 조건
- sizes의 길이는 1 이상 10,000 이하입니다.
- sizes의 원소는 [w, h] 형식입니다.
- w는 명함의 가로 길이를 나타냅니다.
- h는 명함의 세로 길이를 나타냅니다.
- w와 h는 1 이상 1,000 이하인 자연수입니다.
입출력 예
![inputoutputex](https://blog.kakaocdn.net/dn/SjirT/btrgFSZrLZy/kwRBhRAKnauWKOYzVNMODk/img.png)
내 풀이
우리는 주어진 명함들을 넣을 수 있는 최소의 지갑 사이즈를 구해야 합니다. 일단 주어진 조건 중에 중요한 조건이 하나 있는데 지갑에 명함을 넣을 때 회전이 가능하다는 것입니다. 이는 명함의 가로가 세로가 될 수도 있고 세로가 가로가 될 수 있다는 것입니다.
그래서 우리는 각각 가로, 세로가 될 수 있는 최대 값을 구하면 됩니다. 하지만 가로, 세로 중 필연적으로 하나의 길이는 작거나 같기 때문에 다음과 같이 가로, 세로를 새롭게 정의할 수 있습니다. 순서는 상관없습니다.
- 가로 : 명함의 가로, 세로 길이 중 길이가 긴 것 중에 최대 값
- 세로 : 명함의 세로, 가로 길이 중 길이가 짧은 것 중에 최대 값
코드로 풀면 명함들을 순차적으로 접근하여 가로, 세로 길이 비교하여 짧은 것은 짧은 것끼리 긴 것은 긴 것끼리 비교하여 최대 값들을 구하고 최종적으로 구한 값들을 곱해주면 원하는 지갑의 면적이 나옵니다.
📝 코드
class Solution {
fun solution(sizes: Array<IntArray>): Int {
var big = 0
var small = 0
sizes.forEach{
if(it[0] > it[1]){
if(big < it[0]) big = it[0]
if(small < it[1]) small = it[1]
}else{
if(big < it[1]) big = it[1]
if(small < it[0]) small = it[0]
}
}
return big * small
}
}
다른 사람의 풀이
예제 1
class Solution {
fun solution(sizes: Array<IntArray>): Int {
var a = 0
var b = 0
for (array in sizes) {
array.sort()
if (array.isNotEmpty()) {
a = array.first().coerceAtLeast(a)
b = array.last().coerceAtLeast(b)
}
}
return a * b
}
}
조금 더 함수형 프로그래밍에 맞게 작성되었습니다.
coerceAtLeast()
fun <T : Comparable<T>> T.coerceAtLeast(minimumValue: T): T
coerceAtLeast()
값이 지정된 minimumValue보다 작지 않은지 확인합니다. 예를 들면 다음과 같습니다.
println(10.coerceAtLeast(5)) // 10
println(10.coerceAtLeast(20)) // 20
배운 점
처음 이 문제를 보았을 때는 가로, 세로 길이들을 따로 배열로 저장하려고 했는데 이렇게 접근하니 고려해야 할 사항들이 너무 많았습니다. 그래서 다시 천천히 다시 생각을 해보고 풀어보니 생각보다 어려운 문제는 아니었던 것 같습니다.
문제를 풀기에 앞서 문제에 대해 명확한 이해를 하고 풀어야 한다는 것이 중요하다는 것을 다시 한번 느꼈습니다. 처음에는 여러 변수를 생성하고 코드가 복잡할 수 있지만 이는 문제에 대한 명확한 이해를 가지고 풀었다면 충분히 간략하게 표현할 수 있다고 생각합니다.
추가적으로 프로그래머스에서 문제를 풀 때, 현재 언어의 버전도 잘 고려해야 할 것 같습니다. 예를 들어 리스트에서 최대 값을 구할 때 보통 저는 maxOrNull()
를 사용하는데 프로그래머스의 kotlin 버전에서는 제공하지 않아서 조금 애를 먹었습니다. 하지만 실제 코딩 테스트에 들어가면 해당 언어 버전의 문서를 제공하니까 실제로 테스트 보실 때 한 번 확인해보면 좋을 것 같습니다.
'컴퓨터 공학 > 알고리즘' 카테고리의 다른 글
[알고리즘 / JAVA] 까먹지 않기 위한 기본 정렬 알고리즘 (0) | 2021.11.10 |
---|---|
[알고리즘 / Kotlin] 프로그래머스 - (10주차)교점에 별 만들기 (0) | 2021.10.17 |
[알고리즘 / Kotlin] 프로그래머스 - 베스트앨범 (0) | 2021.09.24 |
[알고리즘 / Kotlin] 프로그래머스 - 다리를 지나는 트럭 (0) | 2021.09.15 |
[알고리즘 / Kotlin] 프로그래머스 - 위장(해시) (0) | 2021.09.03 |
댓글