알고리즘

[Swift 알고리즘] 프로그래머스_2개 이하로 다른 비트

마라민초닭발로제 2023. 9. 30. 20:53

 

 

해결 방법: 

 

String(number, radix: 2) -> Int를 2진수로 String으로 변환

Int(binaryNumber, radix: 2) -> 2진수 String을 10진수 Int로 변환

이 두가지 방법을 통해서 문제를 풀었음

 

첫번 째 해결방법은 브루스트 포스로 1씩 더해서 풀었는데 시간초과 남

 

두번 째 해결 방법은 2차이가 언제 발생하는지 곰곰하게 생각해봄

- 원하는 수 + 1 의 이진수 값이, 원래 수의 이진수 값과 자릿수가 다를 때 0을 앞에 붙여준다.

eg) 3 -> 11, 4 -> 100 이럴경우 011로 바꿔준다.

- 타겟 값보다 크면서 && 비트가 최대 2개까지 다른 값이 목표

- 그렇게 생각하니 앞부분을 바꾸는 것 보다(2^이 올라가는 부분) 뒷부분을 바꾸는 방식이 값 차이가 덜 나는방법이라고 생각했음

- 앞 부분과 뒷 부분을 어떤 방식으로 나눌까 고민했는데, 비트기준으로 0이 뒷쪽(오른쪽)에 있는 것들은 건드려서 바꾸면 최적의 해라고 결론 지음

- 아래는 예시임


// 1000
// 1001
맨 뒤에 0이 있음 맨 뒤 0을 1로 바꿈
// 1 1100 0111
// 1 1100 1011
중간에 0이 있음. 2진수 비트중에서 0이 제일 뒷쪽에 있는 0을 선택하고 바로 그 다음 index까지 변환함. 이유는 최대 2개의 비트가 다르게 만들어야 하며, 가장 적은 값 차이를 완성시켜야 함.
// 111 0111
// 111 1011

// 0111
// 1011


// 0 1111
// 1 0111

 

 

import Foundation

func solution(_ numbers:[Int64]) -> [Int64] {
    return numbers.map{getNum($0)}
}

func c2(_ number: Int64) -> String {
    return String(number, radix: 2)
}

func c10(_ number: String) -> Int64 {
    return Int64(number, radix: 2)!
}

func getNum(_ number: Int64) -> Int64{
    let tempNum2 = c2(number + 1)
    var targetNum2 = c2(number)
    if tempNum2.count != targetNum2.count {
        targetNum2 = "0" + targetNum2
    }
    var res = targetNum2.map{String($0)}
    let lastIndex = res.enumerated().filter{$0.element == "0"}.last!.offset
    res[lastIndex] = "1"
    if lastIndex !=  targetNum2.count - 1{
        res[lastIndex + 1] = res[lastIndex + 1] == "0" ? "1" : "0"
    }
    return c10(res.joined())
}