|
| 1 | +/** |
| 2 | + * |
| 3 | + * 접근 방법 : |
| 4 | + * - 3개의 숫자를 더한 값이 0이 되는 숫자의 조합 찾는 문제 |
| 5 | + * - for문과 투 포인터 사용해서 숫자 조합 찾도록 접근 |
| 6 | + * - 투 포인터 이동 조건을 정하기 위해서 배열 오름차순으로 정렬 |
| 7 | + * - 합이 0보다 크면 오른쪽 포인터 1 감소하고, 0보다 작으면 왼쪽 포인터 1 증가 |
| 8 | + * - 합이 0인 경우에는, 결과값에 조합 저장하고, 포인터 2개 모두 이동시키기 |
| 9 | + * - 조합 중복 제거하기 위해서, 첫 번째 숫자와 두 세 번째 숫자 지정할 때 값 같은지 체크해서 같으면 다음 숫자로 넘어가도록 처리 |
| 10 | + * |
| 11 | + * 시간복잡도 : O(n^2) |
| 12 | + * - 배열 정렬 O(nlogn) |
| 13 | + * - for문 순회하고 내부에서 while문으로 요소 모두 순회하니까 O(n^2) |
| 14 | + * |
| 15 | + * 공간복잡도 : |
| 16 | + * - 포인터 변수, sum 변수만 사용해서 O(1) |
| 17 | + * |
| 18 | + * 배운 점 : |
| 19 | + * - Set을 활용해서 마지막에 중복 제거하려고 했는데 참조값이라서 원하는대로 동작 안했다. 결과값에 추가하고 중복 제거하는 것보다 추가하기 이전에 중복 제거하는 방식 고려해보기. |
| 20 | + */ |
| 21 | + |
| 22 | +function threeSum(nums: number[]): number[][] { |
| 23 | + const result: number[][] = []; |
| 24 | + // 투 포인터 사용하기 위해서 배열 정렬 |
| 25 | + nums.sort((a, b) => a - b); |
| 26 | + |
| 27 | + for (let i = 0; i < nums.length - 2; i++) { |
| 28 | + // 중복 조합 제거하기 위해서 같은 값인 경우 넘어가도록 처리 |
| 29 | + if (i > 0 && nums[i] === nums[i - 1]) continue; |
| 30 | + |
| 31 | + let leftPointer = i + 1, |
| 32 | + rightPointer = nums.length - 1; |
| 33 | + |
| 34 | + while (leftPointer < rightPointer) { |
| 35 | + const sum = nums[i] + nums[leftPointer] + nums[rightPointer]; |
| 36 | + |
| 37 | + if (sum < 0) leftPointer++; |
| 38 | + else if (sum > 0) rightPointer--; |
| 39 | + else { |
| 40 | + result.push([nums[i], nums[leftPointer], nums[rightPointer]]); |
| 41 | + |
| 42 | + // 중복 조합 제거하기 위해서 같은 값인 경우 넘어가도록 처리 |
| 43 | + while ( |
| 44 | + leftPointer < rightPointer && |
| 45 | + nums[leftPointer] === nums[leftPointer + 1] |
| 46 | + ) |
| 47 | + leftPointer++; |
| 48 | + while ( |
| 49 | + leftPointer < rightPointer && |
| 50 | + nums[rightPointer] === nums[rightPointer - 1] |
| 51 | + ) |
| 52 | + rightPointer--; |
| 53 | + leftPointer++; |
| 54 | + rightPointer--; |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + return result; |
| 60 | +} |
0 commit comments