Skip to content

Commit 1d9e0e1

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 04b8deb + 4c8b68f commit 1d9e0e1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+2929
-25
lines changed

3sum/EcoFriendlyAppleSu.kt

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package leetcode_study
2+
3+
/**
4+
* 주어진 배열의 세 원소의 합이 0인 경우를 구하는 문제. (세 개의 값의 결과는 중복되지 않음)
5+
*
6+
* 주어진 조건
7+
* 3 <= nums.length <= 3000
8+
* -105 <= nums[i] <= 105
9+
*/
10+
11+
/**
12+
* case01. 조합을 사용한 풀이.
13+
* 시간 초과 발생 이유
14+
* -> 모든 가능한 세 개의 조합을 생성하기 때문에 발생.
15+
* 시간 복잡도:
16+
* -> 세 개의 조합 생성 과정: O(n * (n-1) * (n-2)) / 3. 최악의 경우 n = 3000, 4.5 억개 조합 생성
17+
* -> 세 개의 조합 결과 sorting 과정: O(klogk). k = 3
18+
* -> 결과값을 필터링해 합이 0인 배열을 필터하는 과정: O(n)
19+
* 나머지 연산이 세 개의 조합 생성 과정에 영향을 받아 계산 횟수 증가.
20+
*
21+
* 공간 복잡도:
22+
* -> 각 조합을 모두 저장: O(n^3)
23+
*/
24+
fun threeSumUseCombination(nums: IntArray): List<List<Int>> {
25+
// 결과를 담을 Set 자료구조
26+
val processResult = mutableSetOf<List<Int>>()
27+
28+
// 주어진 배열의 크기를 담는 변수
29+
val maxNumber = nums.size
30+
31+
// 조합 배열의 크기
32+
val givenSize = 3
33+
34+
// 나타낼 인덱스를 구하는 배열 초기화
35+
val indices = IntArray(givenSize)
36+
for (i in 0 until givenSize) {
37+
indices[i] = i
38+
}
39+
40+
while (indices[givenSize - 1] < maxNumber) {
41+
processResult.add(indices.map { nums[it] }.sorted())
42+
var i = givenSize - 1
43+
44+
while (i >= 0 && indices[i] == i + maxNumber - givenSize) {
45+
i--
46+
}
47+
48+
if (i >= 0) {
49+
indices[i]++
50+
for (j in i + 1 until givenSize) {
51+
indices[j] = indices[j-1] + 1
52+
}
53+
} else break
54+
}
55+
56+
return processResult.filter { it.sum() == 0 }
57+
}
58+
59+
/**
60+
* case02. 투 포인터를 사용한 풀이
61+
* 조합을 사용한 풀이와 달리 시간 초과가 발생하지 않음. O(n^3)의 시간 복잡도를 O(n^2)으로 줄임
62+
*
63+
* 시간 복잡도:
64+
* -> 주어진 숫자 배열 오름차순으로 정렬: O(nlogn)
65+
* -> 세 개의 숫자를 더하는 로직
66+
* -> 외부 반복문을 통해 주어진 배열 전체 조회: O(n)
67+
* -> 내부 반복문을 통해 start to last index 순회: O(n)
68+
* -> O(n^2)
69+
* ∴ O(nlogn) + O(n^2) => O(n^2)
70+
*
71+
* 공간 복잡도:
72+
* -> 주어진 숫자 배열의 정렬을 담는 공간 필요: O(n)
73+
*/
74+
fun threeSum(nums: IntArray): List<List<Int>> {
75+
val processResult = mutableListOf<List<Int>>()
76+
val sortedNums = nums.sorted()
77+
78+
for (i in sortedNums.indices) {
79+
if (i > 0 && sortedNums[i] == sortedNums[i-1]) continue
80+
81+
var startIndex = i + 1
82+
var lastIndex = sortedNums.size - 1
83+
84+
while (startIndex < lastIndex) {
85+
val sum = sortedNums[i] + sortedNums[startIndex] + sortedNums[lastIndex]
86+
when {
87+
sum == 0 -> {
88+
processResult.add(listOf(sortedNums[i], sortedNums[startIndex], sortedNums[lastIndex]))
89+
while (startIndex < lastIndex && sortedNums[startIndex] == sortedNums[startIndex + 1]) startIndex++
90+
while (startIndex < lastIndex && sortedNums[lastIndex] == sortedNums[lastIndex - 1]) lastIndex--
91+
startIndex++
92+
lastIndex--
93+
}
94+
sum < 0 -> {
95+
startIndex++
96+
}
97+
else -> {
98+
lastIndex--
99+
}
100+
}
101+
}
102+
}
103+
return processResult
104+
}

3sum/Jeehay28.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**
2+
* @param {number[]} nums
3+
* @return {number[][]}
4+
*/
5+
6+
7+
// Time Complexity: O(n^2)
8+
// Space Complexity: O(n^2)
9+
10+
var threeSum = function (nums) {
11+
12+
const sorted = [...nums].sort((a, b) => a - b);
13+
14+
let result = [];
15+
16+
// Loop through the array and pick each number as the first number for the triplet
17+
for (let i = 0; i < sorted.length - 2; i++) {
18+
19+
// skip duplicate values for sorted[middle]
20+
if(i > 0 && sorted[i - 1] === sorted[i]) {
21+
continue;
22+
}
23+
24+
let left = i + 1; // Left pointer starts right after the current middle
25+
let right = sorted.length - 1; // Right pointer starts at the last element
26+
27+
while (left < right) {
28+
const sum = sorted[i] + sorted[left] + sorted[right];
29+
30+
if (sum === 0) {
31+
result.push([sorted[left], sorted[i], sorted[right]]);
32+
33+
// skip duplicates for sorted[left] and sorted[right]
34+
while(left < right && sorted[left] === sorted[left + 1]){
35+
left += 1; // Move left pointer to the right to skip duplicate values
36+
}
37+
38+
while(left < right && sorted[right] === sorted[right - 1]) {
39+
right -= 1; // Move right pointer to the left to skip duplicate values
40+
}
41+
42+
left += 1;
43+
right -= 1;
44+
45+
} else if (sum > 0) {
46+
right -= 1;
47+
48+
} else {
49+
left += 1
50+
}
51+
}
52+
}
53+
54+
return result;
55+
56+
};
57+
58+
59+
// var threeSum = function (nums) {
60+
61+
// i != j, i != k, and j != k can be interpreted as i < j < k
62+
63+
// three nested loops
64+
// time complexity of O(n³)
65+
// Time Limit Exceeded
66+
67+
// let result = [];
68+
69+
// for (let i = 0; i < nums.length - 2; i++) {
70+
// for (let j = i + 1; j < nums.length - 1; j++) {
71+
// for (let k = j + 1; k < nums.length; k++) {
72+
// if (nums[i] + nums[j] + nums[k] === 0) {
73+
// const str = [nums[i], nums[j], nums[k]].sort((a, b) => a - b).join(",")
74+
// result.push(str)
75+
// }
76+
// }
77+
// }
78+
79+
// }
80+
81+
// result = [... new Set(result)].map(str => str.split(",").map(str => +str))
82+
83+
// return result;
84+
85+
// }
86+

3sum/YeomChaeeun.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* 세 숫자의 합이 0이 되는 조합 찾기
3+
* 알고리즘 복잡도:
4+
* - 시간복잡도: O(n^2)
5+
* - 공간복잡도: O(1)
6+
* @param nums
7+
*/
8+
function threeSum(nums: number[]): number[][] {
9+
// 정렬
10+
nums.sort((a, b) => a - b)
11+
let result: number[][] = []
12+
13+
// 투포인터
14+
for (let i = 0; i < nums.length - 2; i++) {
15+
if (i > 0 && nums[i] === nums[i - 1]) continue;
16+
17+
let start = i + 1
18+
let end = nums.length - 1
19+
const target = -nums[i] // 고정 숫자를 이용
20+
// start + end + target === 0 이므로, start + end === -target
21+
22+
while (start < end) {
23+
const sum = nums[start] + nums[end]
24+
if (sum === target) {
25+
result.push([nums[i], nums[start], nums[end]])
26+
27+
// 배열 중복 값 건너뛰기
28+
while (start < end && nums[start] === nums[start + 1]) start++
29+
while (start < end && nums[start] === nums[end - 1]) end--
30+
31+
// 포인터 이동
32+
start++
33+
end--
34+
} else if (sum < target) {
35+
start++
36+
} else {
37+
end--
38+
}
39+
}
40+
}
41+
return result
42+
}

3sum/gwbaik9717.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Time complexity: O(n^2)
2+
// Space complexity: O(n)
3+
4+
/**
5+
* @param {number[]} nums
6+
* @return {number[][]}
7+
*/
8+
var threeSum = function (nums) {
9+
const sumsDict = new Set();
10+
const sortedNums = nums.toSorted((a, b) => a - b);
11+
12+
const n = nums.length;
13+
14+
for (let i = 0; i < n - 2; i++) {
15+
let left = i + 1;
16+
let right = n - 1;
17+
const fixed = sortedNums[i];
18+
19+
const targetSum = 0 - fixed;
20+
21+
while (left < right) {
22+
const currentSum = sortedNums[left] + sortedNums[right];
23+
24+
if (currentSum < targetSum) {
25+
left++;
26+
} else if (currentSum > targetSum) {
27+
right--;
28+
} else {
29+
const key = [fixed, sortedNums[left], sortedNums[right]];
30+
sumsDict.add(key.join(","));
31+
left++;
32+
right--;
33+
}
34+
}
35+
}
36+
37+
return Array.from(sumsDict).map((nums) => nums.split(",").map(Number));
38+
};

3sum/jdy8739.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* @param {number[]} nums
3+
* @return {number[][]}
4+
*/
5+
var threeSum = function(nums) {
6+
const answer = [];
7+
8+
const sorted = nums.sort((a, b) => a - b);
9+
10+
for (let i=0; i<sorted.length; i++) {
11+
if (i > 0 && sorted[i] === sorted[i - 1]) {
12+
// 위 조건으로 중복 숫자 필터
13+
continue;
14+
}
15+
16+
let l = i + 1;
17+
let h = sorted.length - 1;
18+
19+
while (l < h) {
20+
const sum = sorted[i] + sorted[l] + sorted[h];
21+
22+
if (sum === 0) {
23+
const arr = [sorted[i], sorted[l], sorted[h]];
24+
answer.push(arr);
25+
26+
// 아래 반복문으로 중복 숫자 필터
27+
while (l < h && sorted[l] === sorted[l + 1]) l++;
28+
while (l < h && sorted[h] === sorted[h - 1]) h--;
29+
30+
h--;
31+
l++;
32+
}
33+
34+
if (sum > 0) h--;
35+
if (sum < 0) l++;
36+
}
37+
}
38+
39+
return answer;
40+
};
41+
42+
// TC: O(n2)
43+
// SC: O(1)
44+
45+

3sum/jungsiroo.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
class Solution:
2+
def threeSum(self, nums: List[int]) -> List[List[int]]:
3+
# Naive Solution
4+
# Tc : O(n^3) / Sc : O(nC_3)
5+
6+
n = len(nums)
7+
"""
8+
for i in range(n-2):
9+
for j in range(i+1,n-1):
10+
for k in range(j+1, n):
11+
if nums[i]+nums[j]+nums[k] == 0:
12+
ret.add(tuple(sorted([nums[i], nums[j], nums[k]])))
13+
14+
ret = [x for x in ret]
15+
return ret
16+
"""
17+
18+
# Better Solution
19+
# two-sum question with fixed num (traversal in for loop)
20+
# Tc : O(n^2) / Sc : O(n)
21+
ret = []
22+
nums.sort()
23+
24+
for i in range(n):
25+
if i>0 and nums[i] == nums[i-1]:
26+
continue
27+
j, k = i+1, n-1
28+
29+
while j < k:
30+
sum_ = nums[i] + nums[j] + nums[k]
31+
if sum_ < 0 : j += 1
32+
elif sum_ > 0 : k -= 1
33+
else:
34+
ret.append([nums[i], nums[j], nums[k]])
35+
j += 1
36+
37+
while nums[j] == nums[j-1] and j<k:
38+
j += 1
39+
40+
return ret
41+

0 commit comments

Comments
 (0)