본문 바로가기
codingtest

[programmers] 배열의 유사도, 문자열 계산하기, 편지, 약수 구하기, 한 번만 등장한 문자

by 안자두 2023. 3. 6.

📝 [Lv0] 배열의 유사도

👀 문제 설명

두 배열이 얼마나 유사한지 확인해보려고 합니다. 문자열 배열 s1 s2가 주어질 때 같은 원소의 개수를 return하도록 solution 함수를 완성해주세요.

 

🚨 제한 사항

  • 1 ≤ s1, s2의 길이 ≤ 100
  • 1 ≤ s1, s2의 원소의 길이 ≤ 10
  • s1과 s2의 원소는 알파벳 소문자로만 이루어져 있습니다
  • s1과 s2는 각각 중복된 원소를 갖지 않습니다.

 

💻 입출력 예


["a", "b", "c"] ["com", "b", "d", "p", "c"] 2
["n", "omg"] ["m", "dot"] 0

 

✨ 풀이 설명

우선 같은 단어의 개수를 구하라는 말에 Set()이 떠올랐다. 그래서 두 배열을 합쳐 새로운 배열을 생성했고, 이 배열의 길이와 배열을 Set으로 변환한 집합의 크기를 비교해 주었다. Set은 중복되지 않게 저장되기 때문에, 중복이 제거된 만큼 즉, 같은 원소의 개수가 구해지게 된다. 

filter()를 사용해 내부적으로 includes()를 사용할 수도 있지만, 이 방법은 두 번의 반복문을 통해 시간 복잡도가 O(n²)이 된다. 뭐 lv0에서 그만큼은 요구하지 않기 때문에 실행 결과로는 그렇게 큰 차이는 안 보인다.

 

🕵️‍♂️ 코드

function solution(s1, s2) {
  const totalList = [...s1, ...s2];
  return totalList.length - new Set(totalList).size;
}

 


📝 [Lv0] 문자열 계산하기

👀 문제 설명

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의 숫자와 연산자는 공백 하나로 구분되어 있습니다.

 

💻 입출력 예


"3 + 4" 7

 

✨ 풀이 설명

Lv0 문제는 꽤나 비슷한 것들이 많이 보이는 것 같다. 어제 푼 문제와 비슷한 느낌?
eval()로 답을 구할 순 있지만 그걸 원해서 낸 문제가 아니라고 생각하여 다르게 풀어보았다.

우선 split()으로 잘라 배열로 만들어주었다. 짝수 인덱스는 피연산자, 홀수 인덱스는 연산자이므로, 홀수 번째는 연산자를 저장해 주고, 짝수 번째에서 연산자에 따라 계산을 해주었다.

 

🕵️‍♂️ 코드

function solution(my_string) {
  return eval(my_string);
}
 
function solution(my_string) {
  const list = my_string.split(' ');

  let operand = +list[0], operator;
  list.forEach((oper, idx) => {
    if (idx % 2) operator = oper;
    else if (operator === '+') operand += +oper;
    else if (operator === '-') operand -= +oper;
  });
  return operand;
}

 


📝 [Lv0] 편지

👀 문제 설명

머쓱이는 할머니께 생신 축하 편지를 쓰려고 합니다. 할머니가 보시기 편하도록 글자 한 자 한 자를 가로 2cm 크기로 적으려고 하며, 편지를 가로로만 적을 때, 축하 문구 message를 적기 위해 필요한 편지지의 최소 가로길이를 return 하도록 solution 함수를 완성해주세요.

 

🚨 제한 사항

  • 공백도 하나의 문자로 취급합니다.
  • 1 ≤ message의 길이 ≤ 50
  • 편지지의 여백은 생각하지 않습니다.
  • message는 영문 알파벳 대소문자, ‘!’, ‘~’ 또는 공백으로만 이루어져 있습니다.

 

💻 입출력 예


"happy birthday!" 30
"I love you~" 22

 

✨ 풀이 설명

이번 문제는 길이를 구한 다음, 두 배를 해서 반환해 주는 문제였다. 간단하게 풀 수 있었다.

 

🕵️‍♂️ 코드

function solution(message) {
  return message.length * 2;
}

 


📝 [Lv0] 약수 구하기

👀 문제 설명

정수 n이 매개변수로 주어질 때, n의 약수를 오름차순으로 담은 배열을 return하도록 solution 함수를 완성해주세요.

 

🚨 제한 사항

  • 1 ≤ n ≤ 10,000

 

💻 입출력 예


24 [1, 2, 3, 4, 6, 8, 12, 24]
29 [1, 29]

 

✨ 풀이 설명

우선 전체에 대해 반복문을 돌려 일일이 확인하는 방법도 있지만, 그렇게 되면 시간 복잡도가 O(n)이 되기 때문에, 나는 Math.sqrt()를 사용해 제곱근만큼만 돌려주었다. 예를 들어, n이 36일 경우, 가운데인 6까지만 계산을 한다면 뒤의 숫자들의 앞의 숫자들과 페어를 이루기 때문에 n에서 해당 숫자를 나눠주면 값이 나온다.

그래서 코드가 조금 길어지지만 조건문을 추가하는 방식으로 시간 복잡도를 줄여주었다. 36처럼 6으로 겹치는 숫자가 있을 때를 대비하여 i가 Math.sqrt(n) 일 때를 검사해 주었다. 그리고 마지막에 정렬로 마무리해주었다.

 

🕵️‍♂️ 코드

function solution(n) {
  const answer = [];
  for (let i = 1; i <= Math.sqrt(n); i++) {
    if (i === Math.sqrt(n)) answer.push(i);
    else if (!(n % i)) answer.push(n / i, i);
  }
  return answer.sort((a, b) => a - b);
}

 


📝 [Lv0] 한 번만 등장한 문자

👀 문제 설명

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

 

🚨 제한 사항

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

 

💻 입출력 예


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

 

✨ 풀이 설명

어떤 방법을 쓸까 고민을 꽤 했다. 풀이 방법에는 다양한 방법이 있겠지만, Map()을 쓰는 방법, 문자열을 정렬해 자르는 방법 등등이 생각났으나, indexOf()가 문자열 중 해당하는 문자의 가장 앞에 있는 index를 반환한다는 개념을 활용하여 문제를 풀었다. 

우선 Set()으로 중복 문자를 제거해 문자열에 존재하는 하나씩의 문자만 뽑아내어 다시 배열로 변환해주었다.
위에서 말했던 것처럼 indexOf()는 가장 앞에 있는 index를 반환하기 때문에, 문자열의 앞에서 찾은 index와 뒤에서부터 찾은 index가 같다면 그 문자열에는 해당 문자가 하나밖에 없다는 뜻이 된다.
그래서 s를 뒤집은 revS라는 배열을 하나 만들어 사용해 주었다.

filter()를 사용해 존재하는 문자들 중에서 해당 문자가 앞에서 찾은 위치와 뒤에서부터 찾은 위치가 일치하다면 반환해 주는 방법으로 풀이하였다.

다른 분의 풀이에서 lastIndexOf()라는 것을 보게 되었다.(신기해) 이름 그대로 뒤에서부터 index를 찾아주는 함수인데, 이를 사용하면 굳이 문자를 뒤집어서 비교를 하지 않아도 되어 훨씬 편하고 빠르게 구할 수 있을 것 같다. 이를 활용한 문제 풀이도 아래에 함께 올려두었다.

 

🕵️‍♂️ 코드

function solution(s) {
  const words = [...new Set(s)];
  const revS = [...s].reverse();
  const len = s.length;

  return words.filter(word => s.indexOf(word) === len - 1 - revS.indexOf(word)).sort().join('');
}
function solution(s) {
  const words = [...new Set(s)];

  return words.filter(word => s.indexOf(word) === s.lastIndexOf(word)).sort().join('');
}
728x90