본문 바로가기
코딩테스트

[프로그래머스] 1로 만들기

by liz_devel 2025. 1. 19.

🗒 문제


📝 나의 문제풀이

class Solution {
    fun solution(numList: IntArray): Int {
        var count = 0
        
        numList.forEach{
            var current = it
            while( current != 1){
                if(current % 2 == 0){
                   current = current / 2
                    count++
                }else if(current % 2 != 0){
                    current = (current - 1) / 2
                    count++
                }else{
                    current = current
                }
            }
        }
        return count
      }

    }

 


📝 다른 사람의 문제 풀이

class Solution {
    fun solution(num_list: IntArray): Int = num_list.map{check(it, 0)}.sum()

    tailrec fun check(a: Int, cnt: Int): Int = if(a == 1) cnt else check(a / 2, cnt+1)
}

🖊 문제 풀이 시 알면 좋을 것

forEach

  • 설명: 컬렉션의 각 요소에 대해 반복 작업을 수행. 반환값이 없음.
  • 사용 대상: List, Set, Array 등 컬렉션 타입.
val list = listOf(1, 2, 3)
list.forEach { println(it) }

예시 출력
1
2
3

 

tailrec (꼬리 재귀)

  • 설명: 재귀 호출을 최적화하는 키워드. 마지막 호출이 자기 자신일 경우, 컴파일러가 반복문으로 최적화하여 스택 오버플로 방지. -> 테일렉이라고 읽음
  • 사용 대상: 재귀 함수.
tailrec fun factorial(n: Int, acc: Int = 1): Int =
    if (n == 0) acc else factorial(n - 1, n * acc)
println(factorial(5)) // 120

 

왜 tailrec을 사용할까?

  • 코드 가독성은 재귀처럼 유지하면서, 성능은 반복문처럼 효율적으로 만들기 위해.
  • 재귀 함수란 함수가 자기 자신을 호출하는 함수를 뜻함.

📌 마치며

다른 사람의 문제 풀이를 보면 check(a / 2, cnt + 1)  이 부분이 가독성이 떨어진다고 생각했다. 문제에서는 짝수라면 반으로 나누고, 홀수라면 1을 뺀 뒤 반으로 나누라고 나와 있는데 그게 직관적이지 않아서 다시 재귀함수를 이용하여 코드를 짠다면 이런 식으로 변경할 것이다.

tailrac fun check(a:Int, cnt: Int): Int =
	if(a==1) cnt
   	else if(a % 2 == 0) check(a / 2, cnt + 1)
  	else check((a - 1) / 2, cnt + 1)

 

반응형