Code Kata | Review(1)

이진웅·2021년 12월 1일
0

알고리즘

목록 보기
1/14
post-thumbnail

문제

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

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

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

나의 접근법

  1. 빈 배열 생성
  2. 배열을 이중 반복문으로 두 개를 비교한다
  3. i와 j가 다르면 빈 배열로 push
  4. 매 번 길이를 비교해서서 더 크면 갈아치우는 방식
  5. 빈 배열의 length값 return
const str = 'abcabc'

let getLengthOfStr = str => {
  let array = [];
  let compare = [];
  
  for (i=0; i < str.length; i++) {
    compare.push(str[i])
    for (j=1; j < str.length; j++) {
      if (str[i] !== str[j]) {
      	compare.push(str[j])
      }
    }
  }
}

정확하게 기억은 안나는데 이런식으로 풀어보려고 했지만, 막상 코드를 짜보니 문제가 있었다.
반복문은 기관차처럼 앞으로만 가는데, 내가 원하는 것은 문제의 조건에 맞는 배열을 만들고, 다음 순회때 이전에 만든 배열과 비교하면서 계속 결과 값을 갱신해 반환해줘야 했던 것이다.

뭔가 내 생각대로 코드를 짤 수 없었고, 정해진 시간 내에 문제를 풀지 못했다.

어쩔 수 없이 문제를 해결한 다른 분들의 코드를 보고 공부하였다.

풀이

const str = 'abcabcabcd';

  let getLengthOfStr = (str) => {
    let result = 0; // 배열의 길이가 가장 긴 값을 받을 예정
    let compareArr = []; // 비교할 배열

    for (i in str) {
      if (compareArr.indexOf(str[i]) === -1) { // (1) 반복문으로 순회할 때, i가 비교할 배열에 없다면
        compareArr.push(str[i]); // (2-a) 비교할 배열에 넣는다 [a], [ab], [abc]
      } else {	                 // (2-b) 만약 비교할 배열에 i값이랑 일치하는 값이 있다면,
        compareArr.splice(0, 1); // 처음으로 들어온 배열값을 하나씩 지운다 [bca], [cab], [abc]...
        i--; // 그리고 i값이 증가하는 것을 일시적으로 멈춘다
      }
      if (compareArr.length > result) { // (3) 이후 배열의 길이가 result값 보다 크다면
        result = compareArr.length; // 배열의 길이 값을 result값으로 대체한다
      }
    }
    return result; // 4
  };

알고리즘 문제 중 슬라이드 윈도우 문제를 활용한 풀이법이라는데,
비교할 값을 i-- 을 이용해 잠깐 멈추었다가 다시 멈춘 부분부터 순회를 시작하는 방법이 상당히 인상 깊었다.

또 다른 풀이

let getLengthOfStr2 = str => {
    let result = []; // 빈 배열
    let compareStr = ''; // 빈 문자열

    for (i in str) { // (1) str 순회 중
      if (compareStr.includes(str[i])) { // (4) 순회 중 compareStr이란 문자열 속에 같은 값이 있다면 
        compareStr = compareStr.slice(compareStr.indexOf(str[i]) + 1);
      } // (5) compareStr의 index값 + 1. 즉, 같은 값 이후의 배열만 다시 compareStr에 담아준다
      compareStr += str[i]; // (2) compareStr에 한 글자씩 넣어준다
      result.push(compareStr.length); // (3) compareStr의 길이 값을 result에 하나씩 넣어준다
    }
    return Math.max(...result, 0); // (6) 그 중 제일 큰 값을 반환, 혹시 최대 값이 0이라면 0을 반환하도록 값을 따로 준다
  };

slice 메서드는 index값부터 새로운 배열을 만들어 내기 때문에, +1을 해주어 알파벳이 중복됐을때의 index값보다 한 칸 뒤부터 배열이 시작되도록 하게끔 해준다

소감

뭔가 나의 접근법과 비슷한 점도 있었지만, 두 풀이 방법 모두 내가 디테일하게 생각해내긴 어려웠다.
그래도 몇 시간 동안 코드의 진행과정을 분석해보니 이해가 되긴했다

이러한 접근방법이 있는 것을 알게 되었으니, 기억이 옅어질 때 쯤(?) 내 힘으로 다시 풀어서 제대로 이해했는지 확인해봐야겠다

0개의 댓글