문제
https://school.programmers.co.kr/learn/courses/30/lessons/77885
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
풀이
처음에는 기준이 되는 수에서 +1, +2를 한 값과 xor를 하고, 1의 개수를 세는 방식으로 접근했다.
그러나 이 방법은 시간복잡도 면에서 통과할수가 없었다. 1의 개수를 세기위해 비트를 모두 체크해야하는데 범위가 너무 컸을뿐더러, +1 , +2 씩 하면 언제 비트가 2개 이하로 다른 숫자가 나올지도 모르기 때문이다.
한참을 고민해봤으나 이 접근방법은 틀렸다고만 생각이 들었지 뾰족한 수가 생각나지 않아 풀이를 찾아봤고 꽤나 단순했다.
만약 수가 짝수라면 비트의 끝자리는 0일것이다. 2진수에서 첫비트는 1을 나타내니 이는 당연한거다. 따라서 +1의 값으로 처리해주면 된다.
홀수라면 어떨까? 이때는 가장 처음에 나오는 0과, 그 앞의 1을 바꿔주면 된다. (2진수로 변환했을때 0이 없을경우 가장 최상위에 0을 임의로 붙여줘서 처리해주면 된다.)
3 => 011 => 101
5 => 101 => 110
이렇게 하면 가장 낮은 자리수에서 2개의 비트만 바꿈으로써 작은수를 가질 수 있다.
코드
import java.util.*;
class Solution {
public long func(long value){
String res = "";
while(value != 0){
res += Long.toString(value%2);
value/=2;
}
res += "0";
int targetIdx = res.indexOf("0");
res = res.substring(0, targetIdx-1) + "01" + res.substring(targetIdx+1);
return this.changeBinary(res);
}
public long changeBinary(String val){
long weight = 1;
long res = 0;
for(int i=0; i<val.length(); i++){
res += (val.charAt(i)-'0') * weight;
weight*=2;
}
return res;
}
public List<Long> solution(long[] numbers) {
List<Long> answer = new ArrayList<>();
for(int i=0; i<numbers.length; i++){
if(numbers[i]%2 == 0) answer.add(numbers[i]+1);
else answer.add(this.func(numbers[i]));
}
return answer;
}
}
후기
비트 연산인줄 알았는데, 규칙을 잘 찾아야하는 문제였다.. 때로는 이렇게 관찰력이 필요할때도 있구나 싶었다.
자바로 문자열을 다루니까 죽을맛이다. (더불어 풀이만 보고 바로 작성해봤는데 코드도 엄청 지저분하다..)
'프로그래머스' 카테고리의 다른 글
LV2 스킬트리 (0) | 2023.10.05 |
---|---|
LV2 방문길이 (0) | 2023.09.28 |
LV2 n^2 배열 자르기 (0) | 2023.09.26 |
LV2 점프와 순간 이동 (0) | 2023.09.26 |
LV2 괄호 회전하기 (1) | 2023.09.19 |