IT Study/백준 알고리즘

[백준 알고리즘/Kotlin] 4673번 셀프 넘버 (feat. Array의 fill과 초기화 람다 차이)

three kim 2023. 12. 25. 17:02
728x90

 

다른 돌파구가 있을까 생각했지만, 이 문제는 브루트포스.

완전 탐색으로 접근합니다.

 

1. 최종 코드

// 완전 탐색
// (1) 1 ~ 9999, 모든 수 d(n) 계산
// (2) isSelfNumber, d(n)인 수는 false 표기

fun main() {
    var isSelfNumber = BooleanArray(10000) { true }
    
    for (i in 1 until 10000) {
        var num = i
        var sum = i
        while (num > 0) {
            sum += num % 10
            num /= 10
        }
        if (sum < 10000) {
            isSelfNumber[sum] = false
        }
    }
    
    for (i in 1 until 10000) {
        if (isSelfNumber[i] == true) {
            println(i)
        }
    }
}

 

1부터 9999 (10000보다 작은) 사이의 수에서 문제에 주어진 조건을 만족하지 않는 셀프넘버가 아닌 수를 찾

isSelfNumber를 false로 만들었습니다.

 

2. 최적화된 코드

코드를 더 최적화하기 위해 다른 분들의 코드를 살펴보면 중, StringBuilder()를 사용하여 결과를 모은 다음

한 번에 출력하는 방식을 많이 사용하는 듯 보였습니다.

이를 통해 출력에 소요되는 시간을 최적화하는 듯 보였는데요. 저의 코드에도 적용시켜 봤습니다.

fun main() {
    val isSelfNumber = BooleanArray(10000) { true }
    val result = StringBuilder()
    
    for (i in 1 until 10000) {
        var num = i
        var sum = i
        while (num > 0) {
            sum += num % 10
            num /= 10
        }
        if (sum < 10000) {
            isSelfNumber[sum] = false
        }
    }
    
    for (i in 1 until 10000) {
        if (isSelfNumber[i]) {
            result.append("$i\n")
        }
    }
    print(result)
}

 

메모리도, 시간도 꽤 많이 줄여진 듯 보입니다.

 

3. Array의 fill(e), { e } 차이

 

3-1. fill 메서드 사용

val array = BooleanArray(5).fill(true)

여기서 fill(true)는 해당 배열을 true 값으로 채우고, 이 메서드는 Unit을 반환합니다.

따라서 위 코드에서 array는 BooleanArray가 아니라 Unit 타입이 됩니다.

 

3-2. 초기화 람다 { } 사용

val array = BooleanArray(5) { true }

여기서는 배열을 생성할 때 초기화 람다를 사용하여 각 요소를 초기화합니다.

이때 람다는 배열의 각 인덱스에 대해 호출되며, 반환 값이 해당 인덱스의 초기값이 됩니다.

위 코드에서는 모든 값이 true로 초기화됩니다.

 

4. isSelfNumber와 result는 가변 상태인데  val을 사용할까?

val 키워드는 변수에 할당된 값이 변경될 수 없음을 나타냅니다.
그러나 val로 선언된 변수가 참조하는 객체의 내부 상태는 변경될 수 있습니다.

예를 들어, val로 선언된 리스트에 원소를 추가하거나 제거하는 것은 가능합니다.

isSelfNumber 배열은 한 번 생성되면 그 크기와 내용이 변경되지 않습니다. 따라서 val로 선언하는 것이 적절합니다.
하지만 result는 중간에 문자열이 계속해서 추가되므로 내용이 변경됩니다.
이 경우 val로 선언했더라도 참조 자체가 변경되지 않기 때문에 val로 선언해도 무방합니다.