어제 풀었던 모닝 스터디 알고리즘 문제의 비트 연산(shift 연산)을 활용한 풀이를 소개받았다.
기존 코드
func solution(_ n:Int, _ arr1:[Int], _ arr2:[Int]) -> [String] {
return (0..<n).map { arr1[$0] | arr2[$0] } // &, |는 비트 연산자!
.reduce(into: [String]()) { result, num in
var num = num
let bit = (0..<n)
.reduce(into: "") { string, n in
string = num % 2 == 1 ? string + "#" : string + " "
num = num / 2
}.reversed()
result.append(String(bit))
}
}
-> reduce 고차함수 내에서 나머지 연산으로 결과 문자열 생성
num % 2 == 1 ? string + "#" : string + " "
num 변경 필요
reversed() 사용하여 문자열 뒤집음 - (마지막 비트(==가장 오른쪽 비트)부터 연산되어 생성된 문자열이기 때문에 반대로 만들어져있음)
변경 코드
func solution(_ n:Int, _ arr1:[Int], _ arr2:[Int]) -> [String] {
// 공백1 & 공백2 == 공백 0 && 0
// 벽1 || 공백2 == 벽 0 || 1
// 벽 == 1, 공백 == 0
// 1줄을 2진수로 나타냄 -- 주어진 배열은 해당 2진수의 값
return (0..<n).map { arr1[$0] | arr2[$0] }
.reduce(into: [String]()) { result, num in
var temp = ""
for i in 0..<n {
temp = (num >> i & 1) == 1 ? "#" + temp : " " + temp
}
result.append(temp)
}
}
-> reduce 고차함수 내에서 shift 비트 연산으로 문자열 생성
num >> i & 1
: num의 비트를 i만큼 오른쪽으로 밈. (eg. num == 31: 01111)
: & 1로 1과 동일한지 비교 ( eg. 01111 & 00001)
-> 마지막 비트가 1일 때만 1을 반환
=> 비트를 오른쪽으로 밀면서 순서대로 비교
==> 결과값에 따라 "#" 혹은 " "를 temp 문자열에 추가
나머지 연산 대신 비트 연산을 사용하여 더 빠른 비교가 가능하며, temp 문자열에 추가하는 순서를 바꿈으로써 reversed() 메서드의 사용을 삭제