양의 정수 x에 대한 함수 f(x)를 다음과 같이 정의합니다.
x보다 크고 x와 비트가 1~2개 다른 수들 중에서 제일 작은 수
정수들이 담긴 배열 numbers가 매개변수로 주어집니다. numbers의 모든 수들에 대하여 각 수의 f 값을 배열에 차례대로 담아 return 하도록 solution 함수를 완성해주세요.
2진수는 0과 1로만 구성되어 있기 때문에 규칙만 찾는다면 어렵지 않게 풀 수 있었다. 내가 찾은 규칙은 다음과 같다.
1010
, 1110
, ...10
→ 11
, 111010010
→ 111010010
class Solution {
fun solution(numbers: LongArray): LongArray {
var answer: LongArray = longArrayOf()
val s = Stack<Int>()
numbers.map {
// 짝수: 가장 마지막 자리 수를 1로 변경 (10 -> 11)
// 홀수: 1. 가장 마지막 "0"의 자리 수를 1로 변경 (01 -> 11)
// 2. 구한 "0"의 자리수 다음 자리를 0으로 변경 (11 -> 10)
val s = StringBuilder("0" + it.toString(2))
if (it % 2 == 0L) {
s.setCharAt(s.length - 1, '1')
} else {
val idx = s.lastIndexOf("0")
s.setCharAt(idx, '1')
s.setCharAt(idx + 1, '0')
}
answer += s.toString().toLong(2)
}
return answer
}
}
비트 연산이라는 것이 존재한다. 그렇지만 나는 비트 연산을 무서워한다. 뭐 오른쪽으로 한 칸씩 옮기면 값이 1/2배가 되고, 왼쪽으로 한 칸씩 옮기면 2배가 되고 어쩌구 저쩌구는 머리에 잘 들어오지 않는다. 그래서 비트 연산 없이 이 문제를 풀었었는데...
세상에나 역시나 비트 연산을 사용한 풀이가 제일 위에 있었다. 생각해보니 비트 연산을 모르니까 코틀린의 비트연산자나 함수도 제대로 알아보지 않았던 것 같아 이번 기회에 간단히 알아보았다.
inv()
: 모든 비트 반전 (지정되지 않은 상위 비트는 0으로 채워진다.)shr (shift right)
: 부호 비트를 제외한 모든 비트를 오른쪽으로 밀어준다.shl (shift left)
도 있음and
: and 연산을 한다. (비트가 둘 다 1이면 1, 아니면 0)or
: or 연산을 한다. (비트가 하나라도 1이면 1, 아니면 0)xor
: xor 연산을 한다. (비트가 다르면 1, 같으면 0)알아본 내용을 토대로 코드를 해석해보자면..
it
o
p
정말 해석만 했다. 뭔가뭔가 원리는 내 풀이랑 비슷한것도 같은데 제대로 된 이해는 못하겠다.
class Solution {
fun solution(numbers: LongArray): LongArray {
return numbers.map { num -> (num.inv() and num + 1).let { num or it and (it shr 1).inv() } }.toLongArray()
}
}
나는 String 타입은 특정 범위만 어떤 문자열로 변경하지 못하는 줄 알아서 StringBuilder를 사용했는데, 아니 글쎄 replaceRange()
라는 함수가 있는 것이다!
✨
replaceRange(startIndex: Int, endIndex: Int, replacement: CharSequence)
- startIndex ~ endIndex-1 까지의 문자열을 replacement로 바꿔준다.
- startIndex, endIndex 대신 IntRange 형태를 넣어줄 수도 있다!
홀리몰리.. 오늘도 또 알아간다.
class Solution {
fun solution(numbers: LongArray): LongArray {
return numbers.map {
val str = it.toString(2)
if (!str.contains('0')) ("10" + str.drop(1)).toLong(2)
else {
val last = str.lastIndexOf('0')
if (last == str.lastIndex) str.replaceRange(last..last, "1").toLong(2)
else str.replaceRange(last..last + 1, "10").toLong(2)
}
}.toLongArray()
}
}
비트 연산은.. 화이팅 해보는거고, replaceRange
는 정말 많이 사용할 것 같다!