[Code-kata] #2 ~ 3 : Javascript

nomadhj·2022년 5월 11일
0

Code-kata

목록 보기
1/6

Code-kata #2, #3번 자바스크립트 풀이과정


문제 2번

[문제 #2]
reverse 함수에 정수인 숫자를 인자로 받습니다. 그 숫자를 뒤집어서 return해주세요.
x: 숫자 return: 뒤집어진 숫자를 반환!
예를 들어,
x: 1234 return: 4321
x: -1234 return: -4321
x: 1230 return: 321

나의 풀이

  • 먼저 반복문을 활용하여 해당 숫자를 뒤집기 위해 정수를 문자열로 변경한다. (toString() 활용)
  • 이때 부호를 제거하기 위해 Math.abs() 메소드를 활용한다.
  • 반복문을 통해 해당 문자열을 뒤집고, 이를 숫자로 다시 변경하여 리턴한다.
  • 이때 원래 주어진 숫자의 크기를 확인하여, 0보다 작은 경우 -1을 곱해 부호를 다시 살린다.
  • 문자열 '0123'의 경우 숫자로 변환 시 자동으로 123으로 바뀌기에 별도의 처리는 필요 없다.
const reverse = x => {
  let result = '';
  let string = Math.abs(x).toString();
  
  for(let i = string.length -1; i >= 0; i--){
    result += string[i];
  }

  return x >= 0 ? Number(result) : Number(result) * -1;
}

문제 3번

[문제 3번]
String 형인 str 인자에서 중복되지 않은 알파벳으로 이루어진 제일 긴 단어의 길이를 반환해주세요.
str: 텍스트 return: 중복되지 않은 알파벳 길이 (숫자 반환)
예를 들어,
str = "abcabcabc" return 은 3 => 'abc' 가 제일 길기 때문
str = "aaaaa" return 은 1 => 'a' 가 제일 길기 때문
str = "sttrg" return 은 3 => 'trg' 가 제일 길기 때문

나의 풀이

  • 처음 접근할 때 문제의 의도를 잘못 파악하여 애를 먹었다.
  • 처음에는 위 예시의 abcabcabc 문자열의 예를 보고, 단순히 연속 된 문자열을 카운팅하다가 처음 중복되는 문자열(위 예시에서는 a)가 나오는 지점에서 카운팅을 멈추고 해당 값을 별도로 배열에 저장, 반복문이 완료 된 후 배열에서 최대 값을 찾는 식으로 접근했으나, 이 경우 테스트 케이스 8을 통과하지 못하였다.
  • 처음 문제를 푼 방식은 아래와 같다.
const getLengthOfStr = str => {
  // 문자열의 길이가 0인 경우 조기 리턴
  if(str.length === 0) return 0;

  let arrForCompare = [str[0]];
  let count = 1;
  const arrForCount = [];
  
  for(i = 1; i < str.length; i++){
    if(arrForCompare.indexOf(str[i])===-1){
      count += 1;
      arrForCompare.push(str[i]);
    } else {
      arrForCount.push(count);
      count = 1;
      arrForCompare = [str[i]];
    }
  }
  arrForCount.push(count);
  return Math.max(...arrForCount)
}
  • 위 코드를 'abcabcabc'의 경우로 간단히 해석해보자면,

  • 먼저 값의 비교를 위한 배열 arrForCompare에 초기값 a를 넣고 문자열의 두번째부터 해당 배열과 비교해 나간다.

    1. i = 1일 때, 즉 b는 arrForCompare에 포함되지 않기 때문에 arrForCompare.indexOf(str[i])는 -1을 반환한다.
      1-1. 따라서 조건문 if는 true가 되어 count는 2가 되고 b는 arrForCompare에 추가된다.
    2. i = 2일 때, c는 arrForCompare에 포함되지 않기 때문에 arrForCompare.indexOf(str[i])는 -1을 반환한다.
      2-1. 따라서 조건문 if는 true가 되어 count는 3이 되고 c는 arrForCompare에 추가된다.
    3. i = 3일때, a는 arrForCompare에 이미 포함되어 있기 때문에 조건문에서 -1이 아닌 값을 반환한다. ( 이 경우 0을 반환)
      3-1. 따라서 조건문은 false가 되고 count값은 arrForCount에 별도로 저장된 후 1로 초기화 된다.
      3-2. arrForCompare에는 현재 기준으로 초기값이 되는 str[i]를 저장한다.
    4. 위 반복문을 문자열의 길이 만큼 반복하고 반복문이 끝나는 순간에는 마지막으로 현재의 count를 arrForCount에 저장한다.
    5. arrForCount 내부 원소 중 가장 큰 값을 리턴한다.
  • 이 코드를 실행해보면 마지막에 arrForCount는 [3, 3, 3]이되어 최대값인 3을 리턴한다.

  • 보기에는 이상 없어 보이지만 위 코드는 아래와 같은 경우 올바른 값을 리턴하지 못한다.

    만약 주어진 문자열이 str = 'abcdefaghijklmn'일 경우 어떻게 될까?

  • 위 경우는 개인적으로 테스트케이스 8의 경우를 예측해 본것으로, 위 코드에 따르면 f까지 카운팅을 하며 count를 6으로 만들었다가 7번째 문자인 a를 만나는 순간 count를 초기화하여 다시 마지막 문자 n까지 카운팅을 하게 된다.

  • 이 경우 결과 값은 9로 실제 최대값인 14(bcdefaghijklmn)를 리턴하지 않는다.

  • 즉 반복문을 수행 중에 a를 만나는 순간 해당 부분에서 배열을 초기화 할 것이 아니라 기존 배열에서 a의 위치를 확인, a를 포함하여 이전의 배열 원소를 제거해야한다.

  • 즉 끊는 위치가 abcdef / aghijklmn가 아니라 a / bcdefaghijklmn 가 되도록 코드를 구현해야한다.

  • 이를 구현한 코드는 다음과 같다.

const getLengthOfStr = str => {
  // 문자열의 길이가 0인 경우 조기 리턴
  if (str.length === 0) return 0;

  let arrForCompare = [str[0]];
  let count = 1;
  const arrForCount = [];
  
  for (i = 1; i < str.length; i++) {
    let idx = arrForCompare.indexOf(str[i]);
    
    if (idx === -1) {
      count += 1;
      arrForCompare.push(str[i]);
    } else {
      arrForCount.push(count);
      
      arrForCompare = (idx === (i - 1))? [] : arrForCompare.slice(idx+1);  
      count = arrForCompare.length + 1;
      arrForCompare.push(str[i]);
    }
  }
  arrForCount.push(count);

  return Math.max(...arrForCount)
}
profile
프론트엔드 개발과 맥주에 관심 있습니다.

0개의 댓글