문제설명
- x에 n을 더합니다
- x에 2를 곱합니다.
- x에 3을 곱합니다.
이거 3개 잘 조율해서 x를 y로 최소한의 연산을 거쳐서 바꾸면 된다고 한다 !
문제 접근
enum solveLogic {
case addition
case double
case threeple
func execute(_ x: Int, _ y: Int, _ n: Int) -> Int {
switch self {
case .addition:
return x + n
case .double:
return x * 2
case .threeple:
return x * 3
}
}
}
먼저 이전에 배운 enum활용해서 여기에 로직을 한 번 넣은채로 시작을 해봤다.
뒤에서 부터 계산할거니까 다시 로직을 거꾸로 바꿔줬다(y기준으로)
enum solveLogic {
case addition
case double
case threeple
func execute(_ x: Int, _ y: Int, _ n: Int) -> Int {
switch self {
case .addition:
return y - n
case .double:
return y % 2 != 0 ? -1 : y/2
case .threeple:
return y % 3 != 0 ? -1 : y/3
}
}
}
import Foundation
func solution(_ x: Int, _ y: Int, _ n: Int) -> Int {
var min_count = Int.max
func recursive(_ currentValue: Int, _ count: Int) {
if currentValue < x {
return
}
if currentValue == x {
min_count = min(min_count, count)
return
}
if currentValue % 2 == 0 {
recursive(currentValue/2, count+1)
}
if currentValue % 3 == 0 {
recursive(currentValue/3, count+1)
}
recursive(currentValue - n, count+1)
}
recursive(y, 0)
return min_count
}
순간이동 문제 처럼 도착지점에서부터 역으로 계산을 하되, 딱 짤라서 나눠지는거만 나눠주면서 재귀를 반복하면 안되는 애들은 중간에 떨어져나갈 것이고, 카운트로 최솟값을 가려내주면 된다 !
오류
테스트 3
입력값 〉 2, 5, 4
기댓값 〉 -1
실행 결과 〉 실행한 결괏값 9223372036854775807이 기댓값 -1과 다릅니다.
그냥 Int.max값과 같으면 그거는 -1 처리를 해주면 될 것이다.
return min_count
이 코드를 아래로 변경
return min_count == Int.max ? -1 : min_count
결과
테스트 10 〉 실패 (시간 초과) 테스트 11 〉 실패 (시간 초과) 테스트 12 〉 통과 (0.01ms, 16.5MB) 테스트 13 〉 통과 (0.01ms, 16.5MB) 테스트 14 〉 실패 (시간 초과) 테스트 15 〉 실패 (시간 초과) 테스트 16 〉 실패 (시간 초과) 채점 결과 정확성: 50.0 합계: 50.0 / 100.0
import Foundation
func solution(_ x: Int, _ y: Int, _ n: Int) -> Int {
var min_count = Int.max
var memo = [Int: Int]()
func recursive(_ currentValue: Int, _ count: Int) {
if currentValue < x {
return
}
if currentValue == x {
min_count = min(min_count, count)
return
}
if let memoValue = memo[currentValue], memoValue <= count {
return
}
memo[currentValue] = count
if currentValue % 2 == 0 {
recursive(currentValue/2, count+1)
}
if currentValue % 3 == 0 {
recursive(currentValue/3, count+1)
}
recursive(currentValue - n, count+1)
}
recursive(y, 0)
return min_count == Int.max ? -1 : min_count
}
로직 중간에 memoValue를 추가해서 이게 현재 카운팅이 더 적으면 스킵해줄 수 있도록 조건을 하나 추가해줬다.
채점 결과
정확성: 100.0
합계: 100.0 / 100.0
완성코드
import Foundation
func solution(_ x: Int, _ y: Int, _ n: Int) -> Int {
var min_count = Int.max
var memo = [Int: Int]()
func recursive(_ currentValue: Int, _ count: Int) {
if currentValue < x {
return
}
if currentValue == x {
min_count = min(min_count, count)
return
}
if let memoValue = memo[currentValue], memoValue <= count {
return
}
memo[currentValue] = count
if currentValue % 2 == 0 {
recursive(currentValue/2, count+1)
}
if currentValue % 3 == 0 {
recursive(currentValue/3, count+1)
}
recursive(currentValue - n, count+1)
}
recursive(y, 0)
return min_count == Int.max ? -1 : min_count
}
타인의 코드
import Foundation
func solution(_ x:Int, _ y:Int, _ n:Int) -> Int {
let inf = 99999999
var counter: [Int: Int] = [x: 0]
for i in x...1000000 {
if let c = counter[i] {
counter[i + n] = min(counter[i + n, default: inf], c + 1)
counter[i * 2] = min(counter[i * 2, default: inf], c + 1)
counter[i * 3] = min(counter[i * 3, default: inf], c + 1)
}
}
return counter[y] ?? -1
}
var arr = Array(repeating: Int.max, count: y + 1)
백만까지여서 이게 DP로 될줄을 생각안했던 것 같은데 (감으로 한 십만정도까지인줄?) 이게 훨씬 갈겨하고 쉽게 풀 수 있는 방식이니 다음엔 DP도 생각을 해놔야겠다고 생각이 들었다.