📍 타겟 넘버
n개의 음이 아닌 정수들이 있습니다. 이 정수들을 순서를 바꾸지 않고 적절히 더하거나 빼서 타겟 넘버를 만들려고 합니다. 예를 들어 [1, 1, 1, 1, 1]로 숫자 3을 만들려면 다음 다섯 방법을 쓸 수 있습니다.
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
사용할 수 있는 숫자가 담긴 배열 numbers, 타겟 넘버 target이 매개변수로 주어질 때 숫자를 적절히 더하고 빼서 타겟 넘버를 만드는 방법의 수를 return 하도록 solution 함수를 작성해주세요.
성?공?이다. 나는 오늘도 이해를 못했다. 이번에도 탐색 알고리즘을 사용해서 풀어야하는 문제였다. 탐색? 그게 뭐야 난 검색 밖에 모른다. 문제를 어떤 식으로 풀어야 할 지는 알겠다.
-
와 +
를 붙여 나올 수 있는 모든 합을 구한다.근데 어떻게? 코드로 어떻게 표현해야 할 지를 몰라서 결국 오늘도 검색을 해봤다. 근데 가오가 있지 냅다 풀이 코드를 보기 싫었는데, 도저히.. 응용을 할 수가 없었다. 양심상 코틀린 말고 다른 언어의 풀이를 코틀린으로 풀어보자! 해서 파이썬 코드를 코틀린으로 바꾸는 작업만 해줬다.
class Solution {
var answer = 0
fun seek(i: Int, sum: Int, numbers: IntArray, target: Int) {
if (i == numbers.size) {
if (sum == target) answer += 1
return
}
seek(i+1, sum+numbers[i], numbers, target)
seek(i+1, sum-numbers[i], numbers, target)
}
fun solution(numbers: IntArray, target: Int): Int {
seek(0, 0, numbers, target)
return answer
}
}
코드를 작성하고 나서 해석을 해본 건 다음과 같다.
seek(0, 0, [1, 1, 1], 3)
: 처음 solution에서 호출seek(1, 1, [1, 1, 1], 3)
와 B: seek(1, -1, [1, 1, 1], 3)
호출seek(2, 2, [1, 1, 1], 3)
와 seek(2, 0, [1, 1, 1], 3)
호출seek(2, 0, [1, 1, 1], 3)
와 seek(2, -2, [1, 1, 1], 3)
호출[1, 1, 1]
, [1, 1, -1]
, [1, -1, 1]
, [1, -1, -1]
, ...정말.. 혼자서는 절대 못 풀었을 것이다.
위의 내가 푼 풀이를 보면 변하지도 않는 numbers 배열과 target 값을 계속 재귀 함수 호출 시에 넣어주고 있다. 이건 내가 코틀린의 함수를 중첩해서 사용할 수 있다는 사실을 몰랐기 때문이다. 원본 코드인 파이썬 코드에서는 다음 코드처럼 중첩해서 함수를 사용했다.
아직 나는.. 코틀린에 대해서 1도 모르는구나 싶었다. 다음번에는 중첩 함수도 꼭꼭 이용해봐야겠다.
class Solution {
fun solution(numbers: IntArray, target: Int): Int {
var answer = 0
fun dfs(sum: Int,idx: Int){
if(idx<numbers.size-1){
dfs(sum+numbers[idx],idx+1)
dfs(sum-numbers[idx],idx+1)
}
else{
if(sum+numbers[idx] == target) {answer++}
if(sum-numbers[idx] == target) {answer++}
}
}
dfs(0,0)
return answer
}
}
이 풀이 좀 보세요. 나는 이 풀이를 보고 내가 정말 멍청하다는 것을 깨달았다. 프로그래머스 문제 링크를 보면, 문제의 분류가 보이는데 바로 이 곳에 깊이/너비 우선 탐색(DFS/BFS)라고 적혀져 있었다. 나는 이 것만 보고 아! 이 문제는 꼭 탐색 알고리즘을 알고있고, 이해하고 있어야 풀 수 있겠구나! 라는 생각에 갇혀 코틀린스러운 방식을 생각하지 못했다.
코틀린의 함수들을 이용해서 이런 식으로도 풀 수 있다는 게 정말 놀라웠다. 사실 방식은 다 비슷해서 처음 그 방식을 생각하는 게 정말 어려운 것 같다.
class Solution {
fun solution(numbers: IntArray, target: Int): Int {
return numbers.fold(listOf(0)) { list, i ->
list.run {
map { it + i } + map { it - i }
}
}.count { it == target }
}
}
알고리즘 공부 해야 된다!!! 꼭!!! 시간 남을 때 얼른 해놓자. 하우에버! 무서워.. 네버더레스! 해야 돼..