문제 설명
0과 1로 이루어진 어떤 문자열 x에 대한 이진 변환을 다음과 같이 정의합니다.
- x의 모든 0을 제거합니다.
- x의 길이를 c라고 하면, x를 "c를 2진법으로 표현한 문자열"로 바꿉니다.
예를 들어, x = "0111010"이라면, x에 이진 변환을 가하면 x = "0111010" -> "1111" -> "100" 이 됩니다.
0과 1로 이루어진 문자열 s가 매개변수로 주어집니다. s가 "1"이 될 때까지 계속해서 s에 이진 변환을 가했을 때, 이진 변환의 횟수와 변환 과정에서 제거된 모든 0의 개수를 각각 배열에 담아 return 하도록 solution 함수를 완성해주세요.
제한사항
s의 길이는 1 이상 150,000 이하입니다.
s에는 '1'이 최소 하나 이상 포함되어 있습니다.
입출력 예
s | result |
"110010101001" | [3,8] |
"01110" | [3,3] |
"1111111" | [4,1] |
입출력 예 설명
입출력 예 #1
"110010101001"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 | 이진 변환 이전 | 제거할 0의 개수 | 0 제거 후 길이 | 이진 변환 결과 |
1 | "110010101001" | 6 | 6 | "110" |
2 | "110" | 1 | 2 | "10" |
3 | "10" | 1 | 1 | "1" |
3번의 이진 변환을 하는 동안 8개의 0을 제거했으므로, [3,8]을 return 해야 합니다.
입출력 예 #2
"01110"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 | 이진 변환 이전 | 제거할 0의 개수 | 0 제거 후 길이 | 이진 변환 결과 |
1 | "01110" 2 3 | 2 | 3 | "11" |
2 | "11" | 0 | 2 | "10" |
3 | "10" | 1 | 1 | "1" |
3번의 이진 변환을 하는 동안 3개의 0을 제거했으므로, [3,3]을 return 해야 합니다.
입출력 예 #3
"1111111"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 | 이진 변환 이전 | 제거할 0의 개수 | 0 제거 후 길이 | 이진 변환 결과 |
1 | "1111111" | 0 | 7 | "111" |
2 | "111" | 0 | 3 | "11" |
3 | "11" | 0 | 2 | "10" |
4 | "10" | 1 | 1 | "1" |
4번의 이진 변환을 하는 동안 1개의 0을 제거했으므로, [4,1]을 return 해야 합니다.
풀이
변수 운용하는게 아이디어가 안떠올라서 함수를 하나 따로 만들어 제거한 0의 개수와 길이값을 이진변환한 것을 리턴받아오는 방식을 사용했다.
function solution(s) {
// 변수 배열, 문자 초기화
let answer = [0, 0];
// 이미 "1" 이라면 초기값 리턴
if (s === "1") return answer;
// 함수를 이용하여 0의 개수 및 길이를 구한다.
let [zero, str] = test(s);
// 횟수 카운트 및 제거한 0의 개수 할당
answer[0]++;
answer[1] = zero;
// 반복문 이용하여 "1"이 될때 까지 반복
while (str !== "1") {
[zero, str] = test(str);
answer[0]++;
answer[1] += zero;
}
return answer;
}
function test(s) {
// 제거한 0의 개수 카운트 및 1의 길이 초기화
let zero = 0;
let str = "";
// 반복문 이용하여 요소가 1이라면 그대로 할당하고 아니라면 0의 개수 카운트
for (let char of s) char === "1" ? str += "1" : zero++;
// 0 제거 후 길이 이진변환
str = str.length.toString(2);
return [zero, str];
}
// answer = [ count, zero ]
// 문자열로 이루어진 2진법의 0을 모두 제거한뒤 count++
// 값이 1이라면 그대로 리턴
시간복잡도는 0(log n)이며 공간복잡도는 0(1)이다.
다른풀이
다른 방법이 떠오르지 않아 GPT의 도움을 받았다.
하나의 함수로 최대한 간결하게 고쳐보았다.
function solution(s) {
let count = 0;
let zeroCount = 0;
while (s !== "1") {
let ones = s.match(/1/g).length;
zeroCount += s.length - ones;
s = ones.toString(2);
count++;
}
return [count, zeroCount];
}
정규표현식을 응용하였으며 시간 복잡도는 O(n log n)이며, 공간 복잡도는 O(1)이다.
function solution(s) {
let count = 0;
let zeroCount = 0;
while (s.length > 1) {
let ones = 0;
for (let i = 0; i < s.length; i++) {
if (s.charAt(i) === "1") ones++;
else zeroCount++;
}
s = ones.toString(2);
count++;
}
return [count, zeroCount];
}
정규표현식을 사용하지 않아 좀 더 최적화되어 시간 복잡도는 O(log n)이며, 공간 복잡도는 O(1)이다.
'개발일지 > TIL' 카테고리의 다른 글
[프로그래머스] 피보나치 수 (0) | 2023.04.27 |
---|---|
[프로그래머스] 다음 큰 숫자 (0) | 2023.04.27 |
[프로그래머스] 올바른 괄호 (0) | 2023.04.20 |
[프로그래머스] 최솟값 만들기 (0) | 2023.04.19 |
[프로그래머스] JadenCase 문자열 만들기 (0) | 2023.04.19 |