문제
String 형인 str 인자에서 중복되지 않은 알파벳으로 이루어진 제일 긴 단어의 길이를 반환해주세요.
str: 텍스트 return: 중복되지 않은 알파벳 길이 (숫자 반환)
예를 들어, str = "abcabcabc" return 은 3 => 'abc' 가 제일 길기 때문
str = "aaaaa" return 은 1 => 'a' 가 제일 길기 때문
str = "sttrg" return 은 3 => 'trg' 가 제일 길기 때문
1시간의 고민을 하며 이런 저런 함수를 대입해봐도 풀지 못했다.. 결국 구글신의 힘을 빌려 답을 본 후, 그 답안이 어떻게 동작하는지 차근차근 분석해보기로 했다.
function getLengthOfStr(str) {
let sliceStr = [];
let lastStr = 0;
for (let i = 0; i < str.length; i++) {
if (sliceStr.indexOf(str[i]) === -1) {
sliceStr.push(str[i]);
if (lastStr < sliceStr.length) {
lastStr = sliceStr.length;
}
} else {
sliceStr = sliceStr.slice(sliceStr.indexOf(str[i]) + 1);
sliceStr.push(str[i]);
}
}
return lastStr;
}
빈 배열을 sliceStr이라는 변수에 할당해준다.
0이라는 값을 lastStr이라는 변수에 할당해준다.
for 문으로 입력받은 str의 길이만큼 순회해준다고 했을 때,
sliceStr.indexOf(str[i]) === -1
, 즉, str의 i번째 인덱스가 sliceStr 배열의 인덱스가 아닐 때 (중복이 되지 않았을 때), sliceStr의 인덱스로 str[i] 값을 push 해 주고,
lastStr은 0으로 설정해 두었고, 이 0보다 생성한 배열의 길이가 커졌을 때, lastStr을 배열의 길이 값으로 재할당해주었다.
만약, sliceStr.indexOf(str[i]) !== 1
일때는, (중복 되었을 때), sliceStr.slice(sliceStr.indexOf(str[i] + 1) 로 이전에 만들었던 배열을 없애고 새로운 배열을 시작해 준다.
그리고 for문으로 순회가 끝나면 배열의 길이값인 lastStr을 return 해준다.
여기서, 주어진 str이 'abcabc'라는 문자열로 가정해보자.
for문의 첫 번째 순회에서, i = 0이고 sliceStr에는 아무 요소도 없기 때문에, 'a'는 sliceStr의 0번째 인덱스로 들어가고, lastStr은 1이 된다. 그 다음 'b' 역시 'a'와 중복되지 않기 때문에 1번째 인덱스로 들어가고, lastStr은 2가 된다. 'c'도 마찬가지로 2번째 인덱스로 들어가고, lastStr은 3이 된다. 여기서 'a'가 다시 등장하면서 else 구문으로 넘어가게 되는데, 이 상황에서의 else 구문을 해석하면 sliceStr.indexOf('a')는 현재 sliceStr이 ['a', 'b', 'c'] 이기 때문에 0이 되고, 그렇다면 sliceStr.slice(0 + 1)인, ['b', 'c'] 가 출력되게 된다. 여기서 push로 새로 등장한 'a'를 넣게 되면서 이번 순회에서의 결과값은 ['b', 'c', 'a']가 되게 된다. 그 뒤의 인덱스들도 'b', 'c'가 중복이 되면서 최종적으로 만들어 지는 배열은 ['a', 'b', 'c'] 이며 return 값은 그 배열의 길이인 3이 된다.
정말 접근하기 힘들고 생각을 많이해야 했던 문제였다. 처음에는 답을 봐도 뭔 소린지 이해가 잘 되지 않았었는데, 코드 하나하나 분석을 해보면서 접근해보니 이해를 할 수 있었다. 코드 카타를 하면서 바로 푸는것도 중요하지만 남의 코드를 해석하는 능력도 키워야겠다는 생각이 들었다!