[Code Kata] Week1 - Day3

JU CHEOLJIN·2021년 8월 21일
0

Algorithm

목록 보기
15/16
post-thumbnail

문제

String 형인 str 인자에서 중복되지 않은 알파벳으로 이루어진 제일 긴 단어의 길이를 반환해주세요.

str: 텍스트 return: 중복되지 않은 알파벳 길이 (숫자 반환)

예를 들어, str = "abcabcabc" return 은 3 => 'abc' 가 제일 길기 때문
str = "aaaaa" return 은 1 => 'a' 가 제일 길기 때문
str = "sttrg" return 은 3 => 'trg' 가 제일 길기 때문

풀이

문제 접근

step 1. 단어 만들기

중복되지 않은 알파벳을 계속 붙여서 단어를 만들어 내야한다. 이를 하기 위해서 for 반복문과 인덱스를 이용했다. 아래와 같이 더하기 연산자를 통해서 문자열에 다음 문자열을 붙여주도록 했다.

let acc = "";
acc += strArray[i]

step 2. 단어 길이 저장하기

2중 for문을 이용해서 더해갈 문자열을 계속 찾아갈 수 있도록 해야했다. 또한, 문자열을 붙이는 경우에 조건을 걸어서 기존 저장되어 있는 문자열에 새로 붙일 문자열이 없는 경우에만 붙일 수 있도록 해야 한다.

if (acc.indexOf(strArray[j]) === -1) {
  acc += strArray[j];
}

그런데, 문자열이 있는 경우에는 더하지 않고 새로운 문자열을 만들어야 한다. 이 경우에 for문을 통해서 각 문자열을 시작점으로 계속 반복하고 있으므로 이전까지 단어를 제외하고 새롭게 시작하여 만들도록 추가했다.

else {
        if (acc.length > max) {
          max = acc.length;
          acc = strArray[j];
        } else {
          acc = strArray[j];
        }

이 때, max라는 변수를 통해서 그 동안 만들어진 단어의 길이 중에서 가장 긴 길이를 저장할 수 있도록 했다.

step 3. 최종 풀이

const getLengthOfStr = str => {
   // 아래 코드를 작성해주세요.
 if (str.length === 0) {
    return 0;
  }
  let max = 0;
  let strArray = str.split('');
  for (let i = 0; i < strArray.length; i++) {
    let acc = strArray[i];
    for (let j = 1; j < strArray.length; j++) {
      if (acc.indexOf(strArray[j]) === -1) {
        if (acc.length >= max) {
          max = acc.length + 1;
        }
        acc += strArray[j];
      } else {
        if (acc.length > max) {
          max = acc.length;
          acc = strArray[j];
        } else {
          acc = strArray[j];
        }
      }
    }
  }
  return max;
}

위의 코드가 최종 풀이이다. 보이는 것처럼 2중 for문을 사용했고 조건도 복잡하게 들어가 있다. 특히, 공백 문자만 입력되는 경우에 자동으로 처리가 되지 않아서 바로 return으로 0을 반환하는 예외처리를 해주었다.

처음에 reduce()라는 메소드를 사용하려고 했었는데, 이를 사용할 때 재 시작하는 문자열의 위치를 조작하는 것이 쉽지 않아 for문을 통해서 다시 구성을 해보게 됐다. 코드를 한 눈에 보기 어렵고 구성 자체도 깔끔하지 못해 보이는 모습이다.

은정님의 풀이 ✨

const getLengthOfStr = str => {
  let countMax = 0; 
  let countString = “”; 
  
  for(let i=0; i<str.length; i++) {
    let indexOfStr = countString.indexOf(str[i]);
    
    if (countString !== -1) {
      countString = countString.substr(indexOfStr + 1);
    }
    
    countString = countString + str[i];
    countMax = Math.max(countMax, countString.length);
  }
  return countMax;
}

같은 프론트엔드 개발자로 공부하고 계신 은정님의 코드이다. 처음에 countMax 라는 변수와 countString 변수를 선언해 주었다. 여기서countMax 는 단어의 길이를 저장해 줄 변수이고 countString 은 단어 길이를 측정하기 위해 계속 만들어갈 단어들이 저장될 위치이다.

하나의 for문을 통해서 진행하는데 먼저 indexOfStr 을 통해서 현재 단어가 countString 에 있는지, 있다면 그 인덱스 번호를 기억해두고 이를 이용해서 이후 조건들을 처리했다.

먼저, 그 동안 만들어온 단어에 현재 붙일 문자열이 존재한다면 기존 문자열에서 중복된 문자열까지를 제외하였고 남은 단어와 문자열을 붙이게 된다.

예시를 보면, abc + a => bca

만약 지금까지 단어에 붙일 문자열이 포함되지 않는다면 그냥 문자열을 더 붙여준 후에 countMaxcountString.length 중에서 더 큰 것을 countMax 가 기억하도록 한다.

이렇게 for문이 끝난 후에 countMax를 반환하면 가장 긴 단어의 길이를 알 수 있다.

느낀 점

은정님의 코드가 길이만 단순히 짧아진 것이 아니라, 비 효율적인 코드들이 없고 적절한 메소드와 변수를 통해서 원하는 방향으로 잘 돌아가는 것을 알 수 있다.

은정님의 경우에 문제를 접근할 때 직접 써보면서 하시는 모습이 인상 깊었는데 많은 고민 끝에 깔끔하고 이해하기에도 쉬운 코드가 나오게 되었다.

어떤 방식으로 알고리즘 문제에 접근 해야하는지. 더 나아가 실제로 문제를 만나게 됐을 때 어떤 방식으로 접근해야 할지. 고민이 많이 드는 순간이었다.

기억하고 싶은 건, 개발자는 온갖 화려한 코드들을 가져다 붙여 무언가를 만들어 내는 사람이 아니라 남들도 이해할 수 있는 최소한의 코드들로 소통해야한다는 점이다.

profile
사회에 도움이 되는 것은 꿈, 바로 옆의 도움이 되는 것은 평생 목표인 개발자.

0개의 댓글