|
| 1 | +""" |
| 2 | +[결과 요약] |
| 3 | +# 재시도횟수: 4회 |
| 4 | + 1. 모든 문자열 한 번씩 순회하기(실패) |
| 5 | + - 단순 순회가 아니라 실패 시 직전의 중복 문자열 위치를 찾아야 해서 단순 순회로는 처리가 불가함 |
| 6 | + 2. 문자열 상태를 기록하고, 중복된 문자열이 등장했을 때 기존 문자열을 split 하여 다시 순회를 시작하는 방법(힌트 없이 성공한 방식) |
| 7 | + - 연산 결과는 동일하지만 복잡도가 O(n^2)으로 효율적이지는 않음 |
| 8 | + (3부터 구현 방식에 대한 힌트를 참조) |
| 9 | + 3. Sliding Window를 구현(두 개의 포인터, Set) |
| 10 | + - 시간복잡도: O(n) / 공간복잡도: O(n) |
| 11 | + - 중복 발생 시 while문을 사용하여 중복된 문자가 등장하는 위치까지 순차 탐색(이전 문자열을 제거) |
| 12 | + 4. Dict으로 (3)과 같은 로직을 구현 |
| 13 | + - 시간복잡도: O(n) / 공간복잡도: O(n)이지만 dict을 사용하므로 시간 절약 / 메모리는 약간 더 사용함 |
| 14 | + - 인덱스를 순차로 탐색하는 것이 아니라 dict에서 바로 조회하는 방식 |
| 15 | +
|
| 16 | +
|
| 17 | +""" |
| 18 | + |
| 19 | + |
| 20 | +class Solution: |
| 21 | + def lengthOfLongestSubstring(self, s: str) -> int: |
| 22 | + used_characters = dict() |
| 23 | + longest_length = 0 |
| 24 | + start_idx = 0 |
| 25 | + |
| 26 | + for end_idx, c in enumerate(s): |
| 27 | + if c in used_characters: |
| 28 | + duplicated_idx = used_characters[c] |
| 29 | + if duplicated_idx >= start_idx: |
| 30 | + start_idx = duplicated_idx + 1 |
| 31 | + |
| 32 | + used_characters[c] = end_idx |
| 33 | + longest_length = max(longest_length, end_idx - start_idx + 1) |
| 34 | + |
| 35 | + return longest_length |
| 36 | + |
| 37 | + |
| 38 | +""" |
| 39 | +# Set을 이용한 구현(Dict와 복잡도 상으로는 큰 차이 없음) |
| 40 | +class Solution: |
| 41 | + def lengthOfLongestSubstring(self, s: str) -> int: |
| 42 | + used_characters = set() |
| 43 | + longest_length = 0 |
| 44 | + start_idx = 0 |
| 45 | +
|
| 46 | + for end_idx in range(len(s)): |
| 47 | + while s[end_idx] in used_characters: |
| 48 | + used_characters.remove(s[start_idx]) |
| 49 | + start_idx += 1 |
| 50 | +
|
| 51 | + used_characters.add(s[end_idx]) |
| 52 | + # 속도는 if문보다 약간 느리지만 가독성 크게 개선 |
| 53 | + longest_length = max(longest_length, end_idx - start_idx + 1) |
| 54 | +
|
| 55 | + return longest_length |
| 56 | +""" |
| 57 | + |
| 58 | +if __name__ == "__main__": |
| 59 | + solution = Solution() |
| 60 | + |
| 61 | + test_cases = [ |
| 62 | + ("abcabcbb", 3), |
| 63 | + ("bbbbb", 1), |
| 64 | + ("pwwkew", 3), |
| 65 | + ("a", 1), |
| 66 | + ("bb!1 2@!#$1%3", 9), |
| 67 | + ] |
| 68 | + for idx, cases_ in enumerate(test_cases): |
| 69 | + s, answer = cases_ |
| 70 | + result = solution.lengthOfLongestSubstring(s) |
| 71 | + assert ( |
| 72 | + answer == result |
| 73 | + ), f"Test Case {idx} Failed: Expected {answer}, Got {result}" |
0 commit comments