programmers ) coding test 5

Yeonn·2024년 4월 29일
0

coding test

목록 보기
5/13
post-thumbnail

✔️ 코딩테스트 입문

✅ check

  • obj[key]를 활용하여 객체의 키에 바로 접근 및 값 수정하기
  • 스택을 사용한 구조 ?
  • parseInt(string, radix)
  • toString([radix])
  • Math.round()

🌿 한 번만 등장한 문자

🌱 문제 설명

문자열 s가 매개변수로 주어집니다. s에서 한 번만 등장하는 문자를 사전 순으로 정렬한 문자열을 return 하도록 solution 함수를 완성해보세요. 한 번만 등장하는 문자가 없을 경우 빈 문자열을 return 합니다.

🌱 제한 사항

  • 0 < s의 길이 < 1,000
  • s는 소문자로만 이루어져 있습니다.

🌱 입출력 예

sresult
"abcabcadc""d"
"abdc""abcd"
"hello""eho"

🌱 내 코드

const solution = (s) =>{
  let strArr = [...s]
  let countObj = {};
  let answer = [];

  for(let i = 0; i < strArr.length; i ++){
    if(!Object.keys(countObj).includes(strArr[i])){
      countObj[strArr[i]] = 1;
    }else{
      countObj[strArr[i]] ++;
    }
  }
  
  for( key in countObj ){
    if( countObj[key] === 1){
      answer.push(key+'')
    }
  }

  return answer.sort().join('');
}

불필요한 strArr 선언하고 Object.keys(countObj).includes(strArr[i])는 객체 내 모든 키를 배열로 반환하여 검색하는 방식이므로 비효율적인 방식이다.

🌱 다른 사람 코드

function solution(s) {
    let res = [];
    for (let c of s) if (s.indexOf(c) === s.lastIndexOf(c)) res.push(c);
    return res.sort().join('');
}

다른 사람의 코드들을 보다가 for ( let c of s ) 부분을 활용하기로 했다.

🌱 개선된 코드

const solution = (s) => {
  let countObj = {};
  let answer = [];

  // 문자열에서 직접 char를 검색하고 키에 직접 접근하여 초기화 / 값 증가 작동
  for (let char of s) {
    countObj[char] = (countObj[char] || 0) + 1;
  }

  for (let key in countObj) {
    if (countObj[key] === 1) {
      answer.push(key);
    }
  }

  return answer.sort().join('');
}
  • for문을 활용하여 직관적으로 코드를 유지한다.
  • for ( let char of s ): 문자열에서 직접 char을 검색하여 불필요한 배열 선언을 하지 않아 코드가 간결해졌다.
  • countObj[char] = (countObj[char] || 0) + 1;
    • 검색된 char를 키를 객체의 키로 직접 접근하고 초기화 및 값 증가를 작동시킨다.
    • countObj에 이미 char 이라는 키가 있을 경우 countObj[char] 값을 반환하고 +1로 값을 증가시킨다.
    • countObj에 이미 char 이라는 키가 없을 경우 0을 반환해 초기화 한다.


🌿 컨트롤 제트

🌱 문제 설명

숫자와 "Z"가 공백으로 구분되어 담긴 문자열이 주어집니다. 문자열에 있는 숫자를 차례대로 더하려고 합니다. 이 때 "Z"가 나오면 바로 전에 더했던 숫자를 뺀다는 뜻입니다. 숫자와 "Z"로 이루어진 문자열 s가 주어질 때, 머쓱이가 구한 값을 return 하도록 solution 함수를 완성해보세요.

🌱 제한 사항

  • 1 ≤ s의 길이 ≤ 200
  • -1,000 < s의 원소 중 숫자 < 1,000
  • s는 숫자, "Z", 공백으로 이루어져 있습니다.
  • s에 있는 숫자와 "Z"는 서로 공백으로 구분됩니다.
  • 연속된 공백은 주어지지 않습니다.
  • 0을 제외하고는 0으로 시작하는 숫자는 없습니다.
  • s는 "Z"로 시작하지 않습니다.
  • s의 시작과 끝에는 공백이 없습니다.
  • "Z"가 연속해서 나오는 경우는 없습니다.

🌱 입출력 예

sresult
"1 2 Z 3"4
"10 20 30 40"100
"10 Z 20 Z 1"1
"10 Z 20 Z"0
"-1 -2 -3 Z"-3

🌱 내 코드

const solution = (s) => {
  let num = 0;
  const arr = s.split(' ');

  for(let i = 0; i < arr.length; i ++){  
    let char = arr[i]
    
    if( !isNaN(char) && arr[i+1] !== 'Z'){
      num += Number(char);
    }
  }
  
  return num;
}

🌱 다른 사람 풀이

// 스택을 사용한 구조
function solution(s) {
    const stack = []

    s.split(' ').forEach((target) => {
        if(target === 'Z') stack.pop();
        else stack.push(+target) // +: target 문자열을 숫자로 변환
    })

    return stack.length ? stack.reduce((pre, cur) => pre + cur) : 0;
}


🌿 이진수 더하기

🌱 문제 설명

이진수를 의미하는 두 개의 문자열 bin1과 bin2가 매개변수로 주어질 때, 두 이진수의 합을 return하도록 solution 함수를 완성해주세요.

🌱 제한 사항

  • return 값은 이진수를 의미하는 문자열입니다.
  • 1 ≤ bin1, bin2의 길이 ≤ 10
  • bin1과 bin2는 0과 1로만 이루어져 있습니다.
  • bin1과 bin2는 "0"을 제외하고 0으로 시작하지 않습니다.

🌱 입출력 예

bin1bin2result
"10""11""101"
"1001""1111""11000"

🌱 내 코드

const solution = (bin1, bin2) => {  
  const binToDec = (bin) => {   
    if(bin === '0') return 0;
    
    let num = 0;
    const binArr = [...bin].reverse();

    for(let i = 0; i < binArr.length; i ++){
      let char = binArr[i]
      
      char === '0' ? '' : ( i === 0 ? num += 1: num += 2**i )
    }
    return num;
  }
  
  let decNum = binToDec(bin1) + binToDec(bin2)

  const length = Math.max([...bin1].length+ 1,[...bin2].length+ 1 )
  const binNum = Array(length).fill('0')

  for( let i = binNum.length-1; i >= 0; i--){
    if( decNum - 2**i >= 0 ){
      binNum[i] = '1'
      decNum -= 2 ** i;
    }
  }
  
    // binNum을 reverse().join('') 했을 때 맨 앞이 0이 올 경우 맨 앞의 0을 지워야 하므로 Number() 사용
  return Number(binNum.reverse().join('')).toString();
}

🌸 개선된 코드

const solution = (bin1, bin2) => {  
  const binToDec = (bin) => parseInt(bin, 2);
  
  let decNum = binToDec(bin1) + binToDec(bin2);
  
  let binResult = decNum.toString(2);
  
  return binResult;
}
  • parseInt(bin, 2): 자바스크립트 내장함수 parseInt로 이진수 bin을 십진수로 변환하기
  • decNum.toString(2): 자바스크립트 내장함수 toString으로 decNum을 이진수로 변환하기

parseInt(string, radix)

  • string: 숫자로 변환할 값, 문자가 아닐 경우 암묵적으로 문자열로 변환하고 맨 앞 글자가 공백일 경우 생략
  • radix(optional): 진수를 나타내는 2부터 36까지의 정수

toString([radix])

  • 문자열로 변환한다.
let number = 10;
number.toString(); // '10'
  • radix(optional): 진수를 나타내는 2부터 36까지의 정수


🌿 소인수분해

🌱 문제 설명

소인수분해란 어떤 수를 소수들의 곱으로 표현하는 것입니다. 예를 들어 12를 소인수 분해하면 2 2 3 으로 나타낼 수 있습니다. 따라서 12의 소인수는 2와 3입니다. 자연수 n이 매개변수로 주어질 때 n의 소인수를 오름차순으로 담은 배열을 return하도록 solution 함수를 완성해주세요.

🌱 제한 사항

  • 2 ≤ n ≤ 10,000

🌱 입출력 예

nresult
12[2, 3]
17[17]
420[2, 3, 5, 7]

🌱 내 코드

const solution = (n) => {
    var answer = [];
    let curNum = n;
    let count = 2;
    
    while (curNum !== 1) {
        if (curNum % count === 0) {
            answer.push(count)
            curNum = curNum/count
        } else {
            count++
        }
    }
    
    let check = [...new Set(answer)]
    
    return check;
}


🌿 잘라서 배열로 저장하기

🌱 문제 설명

문자열 my_str과 n이 매개변수로 주어질 때, my_str을 길이 n씩 잘라서 저장한 배열을 return하도록 solution 함수를 완성해주세요.

🌱 제한 사항

  • 1 ≤ my_str의 길이 ≤ 100
  • 1 ≤ n ≤ my_str의 길이
  • my_str은 알파벳 소문자, 대문자, 숫자로 이루어져 있습니다

🌱 입출력 예

my_strnresult
"abc1Addfggg4556b"6["abc1Ad", "dfggg4", "556b"]
"abcdef123"3["abc", "def", "123"]

🌱 내 코드

const solution = (my_str, n) => {
  let strArr = [];
  let startIdx = 0;
  
  for( let i = 0; i < Math.ceil([...my_str].length / n) ; i ++){
    strArr.push([...my_str].splice(startIdx, n).join(''));
    startIdx += n
  }
  
  return strArr;
}

🌸 개선된 코드

const solution = (my_str, n) => {
  let strArr = [];
  
  for(let i = 0; i < my_str.length; i += n) {
    strArr.push(my_str.slice(i, i + n));
  }
  
  return strArr;
}

splice는 원본 배열을 수정하므로 startIdx가 잘못된 값을 가질 수 있다 ! 그래서 splice 대신 slice를 사용했다. [...my_str]은 원본 배열 수정으로 인한 에러를 잡기 위해 사용했었지만 이는 메모리 누수가 생길 수 있고, spliceslice로 변경하면서 해당 문제가 사라졌으므로 없앴다.

🌱 다른 사람 풀이

function solution(my_str, n) {
    let res = [];
    for (let i = 0; i < my_str.length; i+=n) res.push(my_str.slice(i, i+n));
    return res;
}


🌿 영어가 싫어요

🌱 문제 설명

영어가 싫은 머쓱이는 영어로 표기되어있는 숫자를 수로 바꾸려고 합니다. 문자열 numbers가 매개변수로 주어질 때, numbers를 정수로 바꿔 return 하도록 solution 함수를 완성해 주세요.

🌱 제한 사항

  • numbers는 소문자로만 구성되어 있습니다.
  • numbers는 "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" 들이 공백 없이 조합되어 있습니다.
  • 1 ≤ numbers의 길이 ≤ 50
  • "zero"는 numbers의 맨 앞에 올 수 없습니다.

🌱 입출력 예

numbersresult
"onetwothreefourfivesixseveneightnine"123456789
"onefourzerosixseven"14067

🌱 내 코드

const solution = (numbers) => {
  const number = {
    'zero': 0,
    'one': 1,
    'two': 2,
    'three': 3,
    'four': 4,
    'five': 5,
    'six': 6,
    'seven': 7,
    'eight': 8,
    'nine': 9,    
  };
	
  // number object에서 key를 활용해 반복문을 돌고 해당하는 key를 값으로 변환
  for( key in number ){
    numbers = numbers.replaceAll(key, number[key])
  }
  
  return Number(numbers);
};

🌸 개선된 코드

const solution = (numbers) => {
  const number = {
    'zero': 0,
    'one': 1,
    'two': 2,
    'three': 3,
    'four': 4,
    'five': 5,
    'six': 6,
    'seven': 7,
    'eight': 8,
    'nine': 9,    
  };
	
  // number object에서 key를 활용해 반복문을 돌고 해당하는 key를 값으로 변환
  for( key in number ){
    numbers = numbers.split(key).join(number[key]);
  }
  
  return Number(numbers);
};

기존의 내 코드는 numbers 안에서 같은 key가 여러 번 나올 경우 반복문을 순회해야 하는 비효율적인 부분이 있다. 이는 아래의 다른 풀이처럼 split().join()을 활용하여 개선할 수 있다.

원본 문자열이 key를 기준으로 split될 때 해당 부분은 공백이 생긴다.

// example: numbers가 'onetwothree' 일 경우
	numbers.split(key) // ['one', 'two']

공백 부분에 대체할 숫자, 즉 키의 값에 해당하는 숫자를 넣기 위해서 join(number[key])를 넣어준다.

🌱 다른 사람 풀이

// index로 접근하여 변환하기 / split
function solution(numbers) {
    const number = ["zero","one","two","three", "four", "five", "six", "seven", "eight", "nine"]
    for(let i = 0 ; i<number.length; i++){
        numbers = numbers.split(number[i]).join(i)
    }
    return +numbers
}

// index로 접근하여 변환하기 / reaplaceAll
function solution(numbers) {
    let numStr = [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ];

    numStr.forEach((str, idx) => {
        numbers = numbers.replaceAll(str, idx);
    });
    return Number(numbers);
}

// replace 로 순회하기, 정규식 사용
function solution(numbers) {
    const obj = {
        zero: 0, one: 1, two: 2, three: 3, four: 4,
        five: 5, six: 6, seven: 7, eight: 8, nine: 9
    };

    const num = numbers.replace(/zero|one|two|three|four|five|six|seven|eight|nine/g, (v) => {
        return obj[v];
    });

    return Number(num);
}


🌿 문자열 계산하기

🌱 문제 설명

my_string은 "3 + 5"처럼 문자열로 된 수식입니다. 문자열 my_string이 매개변수로 주어질 때, 수식을 계산한 값을 return 하는 solution 함수를 완성해주세요.

🌱 제한 사항

  • 연산자는 +, -만 존재합니다.
  • 문자열의 시작과 끝에는 공백이 없습니다.
  • 0으로 시작하는 숫자는 주어지지 않습니다.
  • 잘못된 수식은 주어지지 않습니다.
  • 5 ≤ my_string의 길이 ≤ 100
  • my_string을 계산한 결과값은 1 이상 100,000 이하입니다.
  • my_string의 중간 계산 값은 -100,000 이상 100,000 이하입니다.
    • 계산에 사용하는 숫자는 1 이상 20,000 이하인 자연수입니다.
    • my_string에는 연산자가 적어도 하나 포함되어 있습니다.
    • return type 은 정수형입니다.
  • my_string의 숫자와 연산자는 공백 하나로 구분되어 있습니다.

🌱 입출력 예

my_stringresult
"3 + 4"7

🌱 내 코드

const solution = (my_string) => {
  const str = my_string.split(' ');
  let answer = Number(str[0]);
  
  for( let i = 0; i < str.length; i ++){
    if( str[i + 1] === '+' ){
      answer += Number(str[i+2])
    }
    if( str[i + 1] === '-' ){
      answer -= Number(str[i+2])
    }
  };
  
  return answer;
}

🌱 다른 사람 풀이

// stack 활용하기
function solution(my_string) {
    const stack = [];

    let sign = 1;
    for (const ch of my_string.split(" ")) {
        if (ch === "+") {
            sign = 1;
        } else if (ch === "-") {
            sign = -1;
        } else {
            stack.push(ch * sign);
        }
    }

    return stack.reduce((a,b) => a + b, 0);
}

🌸 스택을 활용한 방법으로 ch 이 + 부호일 경우 양수인 1, - 부호일 경우 음수인 -1을 sign에 대입하고 둘 다 아닐 경우, 즉 숫자일 경우 sign(부호)를 곱해서 stack에 담아준다. 각각의 숫자가 부호를 포함한 양수와 음수로 변환되어 담겨있는 stack 배열을 reduce를 활용해 합산하여 결과를 반환한다.


🌿 구슬을 나누는 경우의 수

🌱 문제 설명

머쓱이는 구슬을 친구들에게 나누어주려고 합니다. 구슬은 모두 다르게 생겼습니다. 머쓱이가 갖고 있는 구슬의 개수 balls와 친구들에게 나누어 줄 구슬 개수 share이 매개변수로 주어질 때, balls개의 구슬 중 share개의 구슬을 고르는 가능한 모든 경우의 수를 return 하는 solution 함수를 완성해주세요.

서로 다른 n개 중 m개를 뽑는 경우의 수 공식: n개 중 m개 뽑기: n! / (n-m)! * m!

🌱 제한 사항

  • 1 ≤ balls ≤ 30
  • 1 ≤ share ≤ 30
  • 구슬을 고르는 순서는 고려하지 않습니다.
  • share ≤ balls

🌱 입출력 예

ballsshareresult
323
5310

🌱 내 코드

const solution = (balls, share) => {
  let answer = 0;
  // n개 중 m개 뽑기: n! / (n-m)! * m!
  
  const factorial = (n) => {
    let result = 1;
    for(let i = 1; i <= n; i++){
      result *= i
    };
    
    return result;
  }  
  
  answer = factorial(balls) / (factorial(balls - share) * factorial(share))
  
  return Math.round(answer);
}

팩토리얼 개념이 계속 사용되므로 팩토리얼을 처리할 함수를 따로 만들어 처리하여 코드를 간결하게 한다.

📍 Math.round(): 인수로 전달된 숫자의 소수점 이하를 반올림한 정수를 반환


0개의 댓글