[프로그래머스] 최소직사각형

neoneoneo·2024년 2월 27일
0

kotlin

목록 보기
5/49

문제

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.
아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.
모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.

나의 풀이

class Solution {
    fun solution(sizes: Array<IntArray>): Int {
        var answer: Int = 0
        var rowArray: Array<Int> = Array(sizes.size) {0}
        var columArray: Array<Int> = Array(sizes.size) {0}
        var max_1: Int = 0
        var max_2: Int = 0        
        for (i in 0..sizes.size-1) {
            if(sizes[i][0] > sizes[i][1]) {
                rowArray[i] = sizes[i][0]
                columArray[i] = sizes[i][1]
            } else {
                rowArray[i] = sizes[i][1]
                columArray[i] = sizes[i][0]         
            }
        }       
        max_1 = rowArray.maxOrNull() ?: 0
        max_2 = columArray.maxOrNull() ?: 0         
        answer = max_1 * max_2 
        return answer

고수의 풀이_1

import kotlin.math.max
import kotlin.math.min
class Solution {
    fun solution(sizes: Array<IntArray>): Int {
        val widths = mutableListOf<Int>()
        val heights = mutableListOf<Int>()
        sizes.forEach {
            widths.add(max(it[0], it[1]))
            heights.add(min(it[0], it[1]))
        }
        return widths.max()!! * heights.max()!!
    }
}

고수의 풀이_2

class Solution {
    fun solution(sizes: Array<IntArray>): Int
        = sizes.map{it.maxOrNull()!!}.maxOrNull()!!*sizes.map{it.minOrNull()!!}.maxOrNull()!!
}

배운점

  • 내가 문제를 풀어나간 접근법은 아래와 같다.
    1. 각 명함의 가로 길이와 세로 길이를 비교하여 더 큰 값을 찾음 -> rowArray에는 큰 값, columArray에는 작은 값들 저장
    2. 그 값들 중에서 가장 큰 값을 찾음 -> max_1, max_2
    3. 그 길이들로 크기를 계산함 -> answer
  • 이 과정에서 선언하는 변수들이 많아지고 반복문에서도 변수를 여러번 불러와서 데이터를 저장해야 했다.
  • 고수의 풀이 1를 보면 내가 했던 접근법과 비슷하게 풀어나가려고 하였으나, 보다 고급 스킬(?)을 이용한 것 같다.
    • mutableListOf()의 활용
      • 가변 리스트를 생성할 때 사용하는 함수로, 명함 크기들이 저장되어 있는 sizes의 크기가 변동성이 있는 변수라 사용이 필요했다. 나 같은 경우에는 최초에 배열을 선언할 때 sizes.size 크기만한 임시 변수들을 선언해서 사용했지만, mutableListOf를 사용할 수도 있었다.
      • mutableList는 .add()로 원소를 추가한다.
    • forEach의 활용
      • 코드를 더 간결하게 쓸 수 있는 치트키 같은 느낌이다.
      • 전통적으로 쓰여지는 for문의 형태와 달리 it을 사용하여 반복문을 돌릴 변수를 명시할 수 있다.
    • !!의 활용
      • !!는 null이 아니라고 단언하는 연산자이다. 특히 프로그래밍을 하다보면 max, min 값을 구하는 라이브러리를 가져다 쓸 때 이게 null 값인지 아닌지 보다 명확하게 처리되기를 원하는 것 같은데, !!를 이용하면 보다 간결하게 코드를 쓸 수 있다. 내 코드에서는 .maxOrNull() ? : 0 이런 식으로 null이면 0을 할당하라고 작성하였다. 받아오는 값에 null이 없다면 괜찮겠지만, null이 있다면 예외처리가 필요하겠다.
  • 고수의 풀이 2는 한 줄로 쓰여졌지만 뭔가 바로 눈에 들어오는 코드는 아니다. 하나씩 해석해보자.
    • sizes.map {it.manOrNull!!} : sizes 배열의 각 행에 대해 최댓값을 찾아 새로운 리스트를 생성하는 부분
    • .maxOrNull!! : 새로운 리스트에서 다시 최댓값을 찾는 부분
    • 이렇게 위의 2개의 파트를 *로 연산하여 크기를 계산하였다.
    • 내 입장에서 특이한건 map을 사용해서 간소화한 것인데, 아직 나에게 부족한 스킬이다.
      • map의 형태 :
        • T : 입력 컬렉션의 요소 타입
        • R : 변환된 컬렉션의 요소 타입
        • transform : 각 요소에 대해 수행할 변환을 정의하는 람다 함수
      • map 사용법 :

[TIL-240227]

0개의 댓글