Skip to content

Commit 49c963f

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents c6c3822 + 2d55165 commit 49c963f

40 files changed

+1463
-0
lines changed

3sum/GangBean.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
class Solution {
2+
public List<List<Integer>> threeSum(int[] nums) {
3+
/**
4+
1. understanding
5+
- integer array nums, find the whole combination of 3 nums, and the sum of the 3 nums equal to 0. And don't allow reusing same indiced number(but can duplicate in value)
6+
2. solve strategy
7+
- brute force
8+
- in every combination, validate sum of the nums equal to 0
9+
- but it can take O(N^3) times where N is the length of input array, and given that the N can be 3000 at most(3 * 10^3), time can be 27 * 10^9, which takes too long...
10+
- sort and two pointers
11+
- sort nums in ascending order, so move the left pointer to right means the sum of window is getting bigger.
12+
- and mid pointer set to left + 1 index
13+
- if sum of pointers is less than 0, then move mid pointer to right, until the sum is bigger than 0, and while processing them, if the sum of pointers is 0, then add the combination to the return list.
14+
- [-4, -1, -1, 0, 1, 2]:
15+
16+
3. complexity
17+
- time: O(N^2) -> each left pointer, you can search at most N-1, and left pointer's range is [0, N-1), so the max length is N-1 for left index pointer.
18+
- space: O(1) -> no extra space is needed
19+
*/
20+
// 0. assign return variable Set
21+
Set<List<Integer>> answer = new HashSet<>();
22+
23+
// 1. sort the num array in ascending order
24+
Arrays.sort(nums); // O(NlogN)
25+
// Arrays.stream(nums).forEach(System.out::println);
26+
27+
// 3. move the mid pointer from left to right to find the combination of which's sum is 0, and if the sum is over 0, and then move right pointer to the left. else if the sum is under 0, then move left pointer to right direction.
28+
for (int left = 0; left < nums.length - 1; left++) {
29+
int mid = left + 1;
30+
int right = nums.length - 1;
31+
while (mid < right) {
32+
// System.out.println(String.format("%d,%d,%d", nums[left], nums[mid], nums[right]));
33+
int sum = nums[left] + nums[mid] + nums[right];
34+
if (sum > 0) {
35+
right--;
36+
} else if (sum == 0) {
37+
answer.add(List.of(nums[left], nums[mid], nums[right]));
38+
right--;
39+
} else {
40+
mid++;
41+
}
42+
}
43+
}
44+
45+
return new ArrayList<>(answer);
46+
}
47+
}
48+

3sum/Gotprgmer.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// 이전에 투포인터를 활용하여 시도했지만 중복된 값들을 처리하는데 어려움이 있었습니다.
2+
// 그래서 해답을 보았고 새로운 방법으로 풀어보았습니다.
3+
// 서로 다른 i와 j 인덱스를 2중 for문으로 진행하면서
4+
// i와 j사이 수들을 set으로 관리합니다.
5+
// set에 -nums[i]-nums[j]가 존재하면 결과 리스트에 추가합니다.
6+
// 시간복잡도 : O(N^2)
7+
// 공간복잡도 : O(N)
8+
class SolutionGotprgmer {
9+
public List<List<Integer>> threeSum(int[] nums) {
10+
// 결과를 저장할 리스트
11+
List<List<Integer>> result = new ArrayList<>();
12+
Set<Integer> set;
13+
Set<List<Integer>> resultSet = new HashSet<>();
14+
List<Integer> numList;
15+
16+
17+
// 리스트 정렬
18+
Arrays.sort(nums);
19+
for(int i=0;i<nums.length-2;i++){
20+
if (i > 0 && nums[i - 1] == nums[i]) continue;
21+
22+
set = new HashSet<>();
23+
for(int j=i+1;j<nums.length;j++){
24+
int checkNum = nums[i]+nums[j];
25+
if(set.contains(-checkNum)){
26+
numList = new ArrayList<>(Arrays.asList(nums[i], -checkNum, nums[j]));
27+
if(!resultSet.contains(numList)){
28+
result.add(numList);
29+
resultSet.add(numList);
30+
}
31+
}
32+
set.add(nums[j]);
33+
}
34+
}
35+
return result;
36+
}
37+
}

3sum/dalpang81.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* 시간복잡도 : O(N^2)
3+
* 공간복잡도 : O(1)
4+
* */
5+
import java.util.*;
6+
7+
class Solution {
8+
public List<List<Integer>> threeSum(int[] nums) {
9+
List<List<Integer>> result = new ArrayList<>();
10+
Arrays.sort(nums);
11+
12+
for (int i = 0; i < nums.length - 2; i++) {
13+
if (i > 0 && nums[i] == nums[i - 1]) {
14+
continue;
15+
}
16+
17+
int left = i + 1;
18+
int right = nums.length - 1;
19+
20+
while (left < right) {
21+
int sum = nums[i] + nums[left] + nums[right];
22+
23+
if (sum == 0)
24+
{
25+
// 합이 0인 경우 결과에 추가
26+
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
27+
28+
// 중복된 값 건너뛰기
29+
while (left < right && nums[left] == nums[left + 1])
30+
left++;
31+
32+
while (left < right && nums[right] == nums[right - 1])
33+
right--;
34+
35+
left++;
36+
right--;
37+
}
38+
else if (sum < 0)
39+
left++;
40+
else
41+
right--;
42+
43+
}
44+
}
45+
return result;
46+
}
47+
}

3sum/eunhwa99.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.List;
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--;
44+
} 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--;
61+
}
62+
}
63+
}
64+
65+
return answer;
66+
}
67+
}
68+
69+

3sum/heypaprika.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# 2Sum을 활용한 풀이
2+
# Note : 정렬 후 푸는 것이 더 직관적이고, 빠름
3+
4+
"""
5+
복잡도 : 예상 -> 예상한 이유
6+
7+
시간 복잡도 : O(n^2) -> nums 배열 2중 for문
8+
공간 복잡도 : O(n) -> 최악의 경우 nums 배열 길이만큼의 딕셔너리 생성
9+
"""
10+
class Solution:
11+
def threeSum(self, nums: List[int]) -> List[List[int]]:
12+
ans_list = set()
13+
added_pair = {}
14+
for target_i, target_number in enumerate(nums):
15+
cur_ans_list = []
16+
num_dict = {}
17+
if target_number in added_pair:
18+
continue
19+
20+
for i in range(target_i + 1, len(nums)):
21+
num_A = nums[i]
22+
num_B = - target_number - num_A
23+
if num_B in num_dict:
24+
cur_ans_list.append(sorted([target_number, num_A, num_B]))
25+
added_pair[target_number] = num_A
26+
num_dict[num_A] = 1
27+
for item in cur_ans_list:
28+
ans_list.add(tuple(item))
29+
return list(ans_list)
30+

3sum/higeuni.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// complexity
2+
// time: O(n^2)
3+
// - sort: O(n log n)
4+
// - for loop: O(n)
5+
// - while loop: O(n)
6+
// space: O(n)
7+
// - sortedNums: O(n)
8+
// - else : O(1)
9+
10+
var threeSum = function(nums) {
11+
const sortedNums = nums.sort((a, b) => a - b)
12+
const lengthOfArray = nums.length;
13+
const answer = [];
14+
15+
for(let i = 0; i < lengthOfArray; i++ ) {
16+
if (i > 0 && nums[i] === nums[i - 1]) continue;
17+
const target = (-1) * sortedNums[i];
18+
19+
let left = i + 1;
20+
let right = lengthOfArray - 1;
21+
22+
while(left < right) {
23+
const sumOfLeftAndRight = sortedNums[left] + sortedNums[right];
24+
const diff = sumOfLeftAndRight - target;
25+
26+
if( diff > 0 ){
27+
right -= 1;
28+
} else if ( diff < 0 ){
29+
left += 1
30+
} else {
31+
answer.push([sortedNums[i], sortedNums[left], sortedNums[right]]);
32+
// 중복되는 부분을 처리하는 과정에서 계속 fail되어 찾아보니 이렇게 해야 통과되었다.
33+
while(left < right && sortedNums[left] === sortedNums[left + 1]) left ++;
34+
while(left < right && sortedNums[right] === sortedNums[right - 1]) right --;
35+
36+
left++;
37+
right--;
38+
}
39+
}
40+
}
41+
return answer
42+
};
43+

3sum/minji-go.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Problem: https://leetcode.com/problems/3sum/
3+
Description: return all the triplets (i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0)
4+
Concept: Array, Two Pointers, Sorting
5+
Time Complexity: O(N²), Runtime 70ms
6+
Space Complexity: O(N), Memory 51.63MB
7+
*/
8+
class Solution {
9+
public List<List<Integer>> threeSum(int[] nums) {
10+
Map<Integer, Integer> number = new HashMap<>();
11+
for(int i=0; i<nums.length; i++) {
12+
number.put(nums[i], number.getOrDefault(nums[i], 0)+1);
13+
}
14+
15+
Arrays.sort(nums);
16+
Set<List<Integer>> set = new HashSet<>();
17+
List<List<Integer>> triplets = new ArrayList<>();
18+
List<Integer> lastTriplet = null;
19+
for(int i=0; i<nums.length-1; i++) {
20+
if(i>0 && nums[i]==nums[i-1]) continue;
21+
22+
for(int j=i+1; j<nums.length; j++){
23+
if(j>i+1 && nums[j]==nums[j-1]) continue;
24+
25+
int target = -(nums[i]+nums[j]);
26+
if(nums[j]>target) continue;
27+
28+
int count = number.getOrDefault(target,0);
29+
if(nums[i]==target) count--;
30+
if(nums[j]==target) count--;
31+
if(count<=0) continue;
32+
33+
List<Integer> triplet = List.of(nums[i], nums[j], target);
34+
if(triplet.equals(lastTriplet)) continue;
35+
lastTriplet = triplet;
36+
triplets.add(triplet);
37+
}
38+
}
39+
return triplets;
40+
}
41+
}

3sum/paragon0107.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import java.util.Arrays;
2+
import java.util.HashSet;
3+
import java.util.List;
4+
import java.util.Set;
5+
6+
class Solution {
7+
public List<List<Integer>> threeSum(int[] nums) {
8+
Set<List<Integer>> set = new HashSet<>();
9+
Arrays.sort(nums);
10+
for (int i = 0; i < nums.length-2; i++) {
11+
int start = i + 1;
12+
int end = nums.length - 1;
13+
while (start < end) {
14+
int sum = nums[i] + nums[start] + nums[end];
15+
if (sum < 0 ) {
16+
start++;
17+
} else if (sum > 0) {
18+
end--;
19+
}else {
20+
set.add(Arrays.asList(nums[i], nums[start], nums[end]));
21+
start++;
22+
end--;
23+
}
24+
}
25+
}
26+
return set.stream().toList();
27+
}
28+
}

3sum/taewanseoul.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* 15. 3Sum
3+
* Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
4+
* Notice that the solution set must not contain duplicate triplets.
5+
*
6+
* https://leetcode.com/problems/3sum/description/
7+
*/
8+
function threeSum(nums: number[]): number[][] {
9+
nums.sort((a, b) => a - b);
10+
const triplets: number[][] = [];
11+
12+
for (let i = 0; i < nums.length - 2; i++) {
13+
if (nums[i] > 0 || nums[i] === nums[i - 1]) {
14+
continue;
15+
}
16+
17+
let low = i + 1;
18+
let high = nums.length - 1;
19+
20+
while (low < high) {
21+
const sum = nums[i] + nums[low] + nums[high];
22+
if (sum < 0) {
23+
low++;
24+
} else if (sum > 0) {
25+
high--;
26+
} else {
27+
triplets.push([nums[i], nums[low], nums[high]]);
28+
29+
while (low < high && nums[low] === nums[low + 1]) {
30+
low++;
31+
}
32+
while (low < high && nums[high] === nums[high - 1]) {
33+
high--;
34+
}
35+
low++;
36+
high--;
37+
}
38+
}
39+
}
40+
41+
return triplets;
42+
}
43+
44+
// O(n^2) time
45+
// O(n) space

0 commit comments

Comments
 (0)