2023.04.17 알고리즘

정승원·2023년 4월 17일
0
post-thumbnail
post-custom-banner

📒 목차

📌 3진법 뒤집기
📌 이진 변환 반복하기
📌 문제 출처

📌 3진법 뒤집기

✅ 문제 설명

자연수 n이 매개변수로 주어집니다. n을 3진법 상에서 앞뒤로 뒤집은 후, 이를 다시 10진법으로 표현한 수를 return 하도록 solution 함수를 완성해주세요.

✅ 제한사항

제한사항
n은 1 이상 100,000,000 이하인 자연수입니다.
입출력 예
n : 45
result : 7

n : 125
result : 229

✅ 입출력 예 및 설명

입출력 예 #1

답을 도출하는 과정은 다음과 같습니다.

n (10진법) : 45
n (3진법) : 1200
앞뒤 반전(3진법) : 0021
10진법으로 표현 : 7

따라서 7을 return 해야 합니다.


입출력 예 #2

답을 도출하는 과정은 다음과 같습니다.
n (10진법) : 125
n (3진법) : 11122
앞뒤 반전(3진법) : 22111
10진법으로 표현 : 229

따라서 229를 return 해야 합니다.


✏️ 풀이 1.

function solution(n) {
  console.log(n);
  const answer = [];

  while (n / 3 > 0) {
    console.log(Math.floor(n / 3));
    answer.push(n % 3);
    n = Math.floor(n / 3);
  }
  let fAnswer = 0;
  let reverse = answer.reverse();
  console.log(reverse);
  for (let i = 0; i < reverse.length; i++) {
    fAnswer += reverse[i] * 3 ** i;
    console.log(3 ** i);
  }
  return fAnswer;
}

✏️ 풀이 2.

function solution(n) {
  // 10진법 -> 3진법으로 변환
  n = n.toString(3);

  let reverse = "";
  for (let i = n.length - 1; i >= 0; i--) {
    reverse += n[i];
  }
  // 3진법 -> 10진법으로 변환
  return parseInt(reverse, 3);
}

✏️ 풀이 3.

function solution(n) {
  n = n
    .toString(3) // 10진법 => 3진법으로 변환
    .split("") // 문자열을 배열로 변환
    .reverse() // 배열의 순서를 반전
    .join(""); // 배열을 문자열로 변환
  return parseInt(n, 3);
}

📌 이진 변환 반복하기

✅ 문제 설명

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 : "110010101001"
result : [3, 8]

s : "01110"
result : [3, 3]

s : "1111111"
result : [4, 1]

✅ 입출력 예 설명

입출력 예 #1

"110010101001"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 : 1
이진 변환 이전 : "110010101001"
제거할 0의 개수 : 6
0 제거 후 길이 : 6
이진 변환 결과 : "110"

회차 : 2
이진 변환 이전 : "110"
제거할 0의 개수 : 1
0 제거 후 길이 : 2
이진 변환 결과 : "10"

회차 : 3
이진 변환 이전 : "10"
제거할 0의 개수 : 1
0 제거 후 길이 : 1
이진 변환 결과 : "1"

3번의 이진 변환을 하는 동안 8개의 0을 제거했으므로, [3,8]을 return 해야 합니다.

입출력 예 #2

"01110"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 : 1
이진 변환 이전 : "01110"
제거할 0의 개수 : 2
0 제거 후 길이 : 3
이진 변환 결과 : "11"

회차 : 2
이진 변환 이전 : "11"
제거할 0의 개수 : 0
0 제거 후 길이 : 2
이진 변환 결과 : "10"

회차 : 3
이진 변환 이전 : "10"
제거할 0의 개수 : 1
0 제거 후 길이 : 1
이진 변환 결과 : "1"

3번의 이진 변환을 하는 동안 3개의 0을 제거했으므로, [3,3]을 return 해야 합니다.

입출력 예 #3

"1111111"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 : 1
이진 변환 이전 : "1111111"
제거할 0의 개수 : 0
0 제거 후 길이 : 7
이진 변환 결과 : "111"

회차 : 2
이진 변환 이전 : "111"
제거할 0의 개수 : 0
0 제거 후 길이 : 3
이진 변환 결과 : "11"

회차 : 3
이진 변환 이전 : "11"
제거할 0의 개수 : 0
0 제거 후 길이 : 2
이진 변환 결과 : "10"

회차 : 4
이진 변환 이전 : "10"
제거할 0의 개수 : 1
0 제거 후 길이 : 1
이진 변환 결과 : "1"

4번의 이진 변환을 하는 동안 1개의 0을 제거했으므로, [4,1]을 return 해야 합니다.


✏️ 풀이 1.

function solution(s) {
  let countZero = 0;
  let countTry = 0;
  let answer = [];
  let arr = "";
  while (s !== "1") {
    countTry++;
    for (let i = 0; i < s.length; i++) {
      if (s[i] === "0") {
        countZero++;
      }
    }
    s = s.split("0").join("").length;
    while (s / 2 > 0) {
      arr += Math.floor(s % 2);
      s = Math.floor(s / 2);
    }
    s = arr.split("").reverse().join("");
    arr = "";
  }
  answer.push(countTry);
  answer.push(countZero);
  return answer;
}

✏️ 풀이 2.

function solution(s) {
  let count = 0; // 이진 변환이 시도된 횟수
  let remove = 0; // 0이 제거된 개수
  while (s !== "1") {
    // s가 "1"이 될 때까지 무한하게 이진 변환을 적용
    count++;
    let temp = ""; // s에서 1만 남겨진 문자열 (= 0이 제거된 문자열)
    for (let i = 0; i < s.length; i++) {
      if (s[i] === "0") {
        // "0"이라면 문자열에서 제거
        remove++;
        continue; //해당 부분만 쉬었다가 다음 반복문으로 가기
      }
      // 문자열 "0"이 아니라면 (= "1") 새로운 문자열에 저장
      temp += s[i];
    }
    s = temp.length; // 문자열 "0"이 제거된 문자열의 길이
    s = s.toString(2); // 문자열의 길이를 2진법으로 변환
  }
  return [count, remove];
}

✏️ 풀이 3.

function solution(s) {
    let [ count, remove ] = [ 0, 0 ];

    function recursion(s) {
        if( s === "1" ) {
            return [ count, remove ];
        }
        count++;

        s = s.split("").filter( num => {
            if( num === "0" ) remove++;
            return num === "1"
        }).length;

        return recursion( s.toString( 2 ) );
    }
    return recursion(s);
}

📌 추가학습

✅ 10진수 -> n진수 변환하기

let answer = "";
let num = 10;

// 1. 10진법 -> n진법
while( num > 0 ){
   answer += (num % n);
   num = Math.floor(num / n)
}
console.log(answer)

// 2. toString은 기본적으로 10진법을 기준으로 변환
10..toString(2)

// 3. 10진법으로 바꾸기
const num = 10..toString(2);
parseInt( num, 2 )

✅ 숫자 -> 문자열로 만들기

num = 10;
1. String(num)
// toString 주의점 = 변환하려는 값이 변수에 담겨 있어야 한다!!
2. num.toString()
// ()안에 넣게 되면, 변수에 넣지 않아도 된다.
3. (10).toString()
// .. 점을 두개 붙이면, 변수에 넣지 않아도 된다.
4. 10..toString()

// 소수점
.5 === 0.5
10 === 10.0

✅ while문을 대체하는 (recursion)

let count = 0;
// while문
while(count !== 5) {
   count++;
}
console.log(count)

// recursion
let count = 0;
function recursion() {
  count++;

  // if부분을 어떻게 설정하는가에 따라 얼마나 도는지 정해진다
  if( count > 5 ) {
    console.log("재귀함수 종료")
    return;
  }
  console.log("재귀함수 실행")
  return recursion()
}
recursion();

📌 문제 출처

https://programmers.co.kr/

post-custom-banner

0개의 댓글