|
2 | 2 | import java.util.Arrays; |
3 | 3 | import java.util.List; |
4 | 4 |
|
5 | | -/** |
6 | | - * 문제 풀이 |
7 | | - */ |
8 | | -// -4 -1 -1 0 2 2 |
9 | | -// p1 p2 p3 sum < 0 -> p2 앞으로 |
10 | | -// p1 p2 p3 sum < 0 -> p2 앞으로 |
11 | | -// p1 p2 p3 sum < 0 -> p2 앞으로 |
12 | | -// p1 p2p3 sum = 0 -> p1 앞으로 |
13 | | -// p1 p2 p3 sum = 0 -> p3 값 다른 게 나올 때까지 이동 |
14 | | -// p1 p2 p3 sum < 0 -> p2 앞으로 인데, p2 > p3 되므로 p1 앞으로 |
15 | | -// p1 p2 p3 sum = 0 반복 |
16 | | - |
17 | | -/** |
18 | | - * 시간/공간 복잡도 |
19 | | - */ |
20 | | -// 시간 복잡도 - 순회 횟수: n + (n-1) + (n-2) + .. => O(N^2) |
21 | | -// 공간 복잡도 - 배열을 정렬하는 데 O(n log n)의 공간 + 결과를 저장하는 answer 리스트는 문제의 요구에 따라 O(k)의 공간 = O(n log n) (배열 정렬을 위한 공간) + O(k) (결과 저장 공간) |
22 | | - |
23 | | -class Solution { |
24 | | - public List<List<Integer>> threeSum(int[] nums) { |
25 | | - Arrays.sort(nums); // Sort the array first |
26 | | - List<List<Integer>> answer = new ArrayList<>(); |
27 | | - |
28 | | - for (int pointer1 = 0; pointer1 < nums.length - 2; pointer1++) { |
29 | | - // pointer1 의 중복 값 skip |
30 | | - if (pointer1 > 0 && nums[pointer1] == nums[pointer1 - 1]) { |
31 | | - continue; |
32 | | - } |
33 | | - |
34 | | - int pointer2 = pointer1 + 1; // pointer2 는 pointer1 의 한 칸 앞 |
35 | | - int pointer3 = nums.length - 1; // pointer3 는 끝에서 부터 |
36 | | - |
37 | | - while (pointer2 < pointer3) { |
38 | | - int sum = nums[pointer1] + nums[pointer2] + nums[pointer3]; |
39 | | - |
40 | | - if (sum < 0) { |
41 | | - pointer2++; |
42 | | - } else if (sum > 0) { |
43 | | - pointer3--; |
| 5 | +// 시간 복잡도: O(n^2) - nums 배열을 정렬하는 데 O(nlogn) 소요, 이후 이중 포인터로 O(n^2) |
| 6 | +// 공간 복잡도: O(1) - 결과 리스트를 제외한 추가 공간 사용 없음 |
| 7 | +class Solution{ |
| 8 | + public List<List<Integer>> threeSum(int[] nums){ |
| 9 | + Arrays.sort(nums); |
| 10 | + |
| 11 | + List<List<Integer>> result = new ArrayList<>(); |
| 12 | + |
| 13 | + for(int i=0;i<nums.length-2;i++){ |
| 14 | + if(i>0 && nums[i] == nums[i-1]) continue; // 중복된 값 건너뛰기 |
| 15 | + int left = i+1; |
| 16 | + int right = nums.length-1; |
| 17 | + |
| 18 | + while(left < right){ |
| 19 | + int sum = nums[i] + nums[left] + nums[right]; |
| 20 | + if(sum == 0){ |
| 21 | + result.add(Arrays.asList(nums[i], nums[left], nums[right])); |
| 22 | + while(left < right && nums[left] == nums[left+1]) left++; // 중복된 값 건너뛰기 |
| 23 | + while(left < right && nums[right] == nums[right-1]) right--; // 중복된 값 건너뛰기 |
| 24 | + left++; |
| 25 | + right--; |
| 26 | + } else if(sum < 0){ |
| 27 | + left++; |
44 | 28 | } else { |
45 | | - // sum == 0 |
46 | | - answer.add(Arrays.asList(nums[pointer1], nums[pointer2], nums[pointer3])); |
47 | | - |
48 | | - // pointer2 중복 값 제거 |
49 | | - while (pointer2 < pointer3 && nums[pointer2] == nums[pointer2 + 1]) { |
50 | | - pointer2++; |
51 | | - } |
52 | | - |
53 | | - // pointer3 중복 값 제거 |
54 | | - while (pointer2 < pointer3 && nums[pointer3] == nums[pointer3 - 1]) { |
55 | | - pointer3--; |
56 | | - } |
57 | | - |
58 | | - // 두 값 모두 move |
59 | | - pointer2++; |
60 | | - pointer3--; |
| 29 | + right--; |
61 | 30 | } |
62 | 31 | } |
63 | 32 | } |
64 | | - |
65 | | - return answer; |
| 33 | + return result; |
66 | 34 | } |
67 | 35 | } |
68 | | - |
69 | | - |
0 commit comments