코딩테스트 하면서, 고민을 많이했거나 못풀었거나 혹은 추후에 다시 볼만한 문제를 골라서만 기록하려고 한다.
https://school.programmers.co.kr/learn/courses/30/lessons/148652
1
의 갯수가 몇개인지 구하는 문제이다.그럼 유사칸토어 비트열이 무엇일까?
즉, 번째가 증가할 수록, 1
->"11011" ,0
->"00000" 로 변하면서 늘어 나는 비트열을 말한다.
그래서 문자열의 길이도 1→ 5→ 25→ 125
로 규칙적으로 늘어난다.
l,r
의 값 범위도 5^n이 된다.l
+ 10,000,000 의 의미는 뭘까?[이전 비트열][이전 비트열] [0밖에 없는 존][이전 비트열][이전 비트열]
l
~ r
까지 사이의 1의 갯수long type
시행착오를 겪어봤지만, 실패했다.
l
은 2구역에, r
은 4구역에 있다고 가정하자l
로 시작하고, 5구역 끝에서 끝나야한다. r
에서 끝나야 한다.하지만, 다른 경우도 있을 수 있으니 검증해보자.
l
과 r
이 같은 구역에 있는 경우이다.l
과 r
이 다른 구간에 있어 나눠지는 경우,이둘은 이미 위에서 언급했던 2가지 경우가 반복되는 것이다보니, 이것을 이용하여 풀 수 있을 것같다.
그리고 마지막의 경우는 본인위치를 제외한 나머지의 1의 갯수를 계산했기 때문에, l
과 r
의 위치가 1인지 0 인지 만 확인하여 추가해주면 된다.
class Solution {
int answer;
public int solution(int n, long l, long r) {
answer = 0;
long areaLength = 1;
int countOne =1;
while(n>1){
areaLength *= 5L;
countOne *= 4;
n--;
}
dfs(areaLength, countOne, l,r);
return answer;
}
private void dfs(long areaLength, int countOne, long start, long end){
if(areaLength == 1L){
long c = end - start + 1;
if(c >= 3 || end ==3 || start == 3){
c--;
}
answer +=c;
return;
}
long startArea = start / areaLength;
if(start % areaLength > 0){
startArea++;
}
long endArea = end/areaLength;
if(end % areaLength > 0) {
endArea++;
}
if(endArea > startArea){// 같은 구역이 아니면
long includArea = endArea - startArea - 1L;
if(startArea%5 < 3 && ((endArea)%5 >3 || endArea%5 == 0)){ // 3구역 포함
includArea--;
}
answer += (includArea*countOne);
if(startArea != 3) {
dfs(areaLength / 5, countOne / 4, start, startArea * areaLength);
}
if(endArea != 3){
dfs(areaLength/5 ,countOne/4, (endArea-1)*areaLength+1 , end);
}
}
else{
if(startArea == 3) return;
dfs(areaLength/5 ,countOne/4, start, end);
}
}
}
여행 가기 전 날에도 알고리즘 문제를 푸시다니.. 대단하십니다 !!