|
| 1 | +from typing import List |
| 2 | +from unittest import TestCase, main |
| 3 | +from collections import defaultdict |
| 4 | + |
| 5 | + |
| 6 | +class Solution: |
| 7 | + def twoSum(self, nums: List[int], target: int) -> List[int]: |
| 8 | + return self.solveWithMemoization(nums, target) |
| 9 | + |
| 10 | + """ |
| 11 | + Runtime: 3762 ms (Beats 5.00%) |
| 12 | + Time Complexity: O(n ** 2) |
| 13 | + - 크기가 n인 nums 배열을 2중으로 조회하므로 O(n ** 2) |
| 14 | +
|
| 15 | + Memory: 17.42 MB (Beats 61.58%) |
| 16 | + Space Complexity: ? |
| 17 | + """ |
| 18 | + def solveWithBruteForce(self, nums: List[int], target: int) -> List[int]: |
| 19 | + for i in range(len(nums)): |
| 20 | + for j in range(len(nums)): |
| 21 | + if i != j and nums[i] + nums[j] == target: |
| 22 | + return [i, j] |
| 23 | + |
| 24 | + """ |
| 25 | + Runtime: 52 ms (Beats 89.73%) |
| 26 | + Time Complexity: O(n) |
| 27 | + 1. nums 배열을 돌며 idx를 저장하는 dict 생성에 O(n) |
| 28 | + 2. 첫 숫자를 선택하기 위해 len(nums)를 for문으로 조회하는데 O(n) |
| 29 | + > O(2n) ~= O(n) |
| 30 | +
|
| 31 | + Memory: 19.96 MB (Beats 8.42%) |
| 32 | + Space Complexity: O(n) |
| 33 | + - 크기가 n인 defaultdict 변수 사용 |
| 34 | + """ |
| 35 | + def solveWithMemoization(self, nums: List[int], target: int) -> List[int]: |
| 36 | + num_to_idx_dict = defaultdict(list) |
| 37 | + for idx, num in enumerate(nums): |
| 38 | + num_to_idx_dict[num].append(idx) |
| 39 | + |
| 40 | + for i in range(len(nums)): |
| 41 | + first_num = nums[i] |
| 42 | + second_num = target - nums[i] |
| 43 | + |
| 44 | + if first_num != second_num: |
| 45 | + if not (len(num_to_idx_dict[first_num]) and len(num_to_idx_dict[second_num])): |
| 46 | + continue |
| 47 | + else: |
| 48 | + if not (2 <= len(num_to_idx_dict[first_num])): |
| 49 | + continue |
| 50 | + |
| 51 | + first_idx = num_to_idx_dict[first_num].pop() |
| 52 | + second_idx = num_to_idx_dict[second_num].pop() |
| 53 | + |
| 54 | + if first_num != second_num: |
| 55 | + return [first_idx, second_idx] |
| 56 | + else: |
| 57 | + return [second_idx, first_idx] |
| 58 | + |
| 59 | + |
| 60 | +class _LeetCodeTestCases(TestCase): |
| 61 | + def test_1(self): |
| 62 | + nums = [2, 7, 11, 15] |
| 63 | + target = 9 |
| 64 | + output = [0, 1] |
| 65 | + self.assertEqual(Solution.twoSum(Solution(), nums, target), output) |
| 66 | + |
| 67 | + def test_2(self): |
| 68 | + nums = [3,2,4] |
| 69 | + target = 6 |
| 70 | + output = [1, 2] |
| 71 | + self.assertEqual(Solution.twoSum(Solution(), nums, target), output) |
| 72 | + |
| 73 | + def test_3(self): |
| 74 | + nums = [3, 3] |
| 75 | + target = 6 |
| 76 | + output = [0, 1] |
| 77 | + self.assertEqual(Solution.twoSum(Solution(), nums, target), output) |
| 78 | + |
| 79 | + def test_4(self): |
| 80 | + nums = [3, 2, 3] |
| 81 | + target = 6 |
| 82 | + output = [0, 2] |
| 83 | + self.assertEqual(Solution.twoSum(Solution(), nums, target), output) |
| 84 | + |
| 85 | + |
| 86 | +if __name__ == '__main__': |
| 87 | + main() |
0 commit comments