-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/main'
- Loading branch information
Showing
197 changed files
with
7,195 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
""" | ||
첫번째 풀이 -> 달레의 코드 풀이 | ||
1) sort와 two pointer를 활용한 풀이 | ||
2) has_set 을 활용한 중복 제거 | ||
두번째 풀이 -> Neetcode 풀이 | ||
1) sort와 two pointer를 활용한 풀이 | ||
2) while loop 를 활용한 중복 제거 | ||
Time: O(n^2) = O(n) * O(n) | ||
Space: O(n) | ||
""" | ||
|
||
|
||
class Solution: | ||
def threeSum(self, nums: List[int]) -> List[List[int]]: | ||
nums.sort() | ||
res = set() | ||
n = len(nums) | ||
|
||
for i in range(n): | ||
l, r = i + 1, n - 1 | ||
while l < r: | ||
summ = nums[i] + nums[l] + nums[r] | ||
if summ < 0: | ||
l += 1 | ||
elif summ > 0: | ||
r -= 1 | ||
else: | ||
res.add((nums[i], nums[l], nums[r])) | ||
l += 1 | ||
return list(res) | ||
|
||
|
||
class Solution: | ||
def threeSum(self, nums: List[int]) -> List[List[int]]: | ||
nums.sort() | ||
res = [] | ||
n = len(nums) | ||
|
||
for i in range(n): | ||
l, r = i + 1, n - 1 | ||
|
||
if i > 0 and nums[i] == nums[i - 1]: | ||
continue | ||
|
||
while l < r: | ||
summ = nums[i] + nums[l] + nums[r] | ||
if summ < 0: | ||
l += 1 | ||
elif summ > 0: | ||
r -= 1 | ||
else: | ||
res.append([nums[i], nums[l], nums[r]]) | ||
l += 1 | ||
while nums[l] == nums[l - 1] and l < r: | ||
l += 1 | ||
|
||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package leetcode_study | ||
|
||
/** | ||
* 주어진 배열의 세 원소의 합이 0인 경우를 구하는 문제. (세 개의 값의 결과는 중복되지 않음) | ||
* | ||
* 주어진 조건 | ||
* 3 <= nums.length <= 3000 | ||
* -105 <= nums[i] <= 105 | ||
*/ | ||
|
||
/** | ||
* case01. 조합을 사용한 풀이. | ||
* 시간 초과 발생 이유 | ||
* -> 모든 가능한 세 개의 조합을 생성하기 때문에 발생. | ||
* 시간 복잡도: | ||
* -> 세 개의 조합 생성 과정: O(n * (n-1) * (n-2)) / 3. 최악의 경우 n = 3000, 4.5 억개 조합 생성 | ||
* -> 세 개의 조합 결과 sorting 과정: O(klogk). k = 3 | ||
* -> 결과값을 필터링해 합이 0인 배열을 필터하는 과정: O(n) | ||
* 나머지 연산이 세 개의 조합 생성 과정에 영향을 받아 계산 횟수 증가. | ||
* | ||
* 공간 복잡도: | ||
* -> 각 조합을 모두 저장: O(n^3) | ||
*/ | ||
fun threeSumUseCombination(nums: IntArray): List<List<Int>> { | ||
// 결과를 담을 Set 자료구조 | ||
val processResult = mutableSetOf<List<Int>>() | ||
|
||
// 주어진 배열의 크기를 담는 변수 | ||
val maxNumber = nums.size | ||
|
||
// 조합 배열의 크기 | ||
val givenSize = 3 | ||
|
||
// 나타낼 인덱스를 구하는 배열 초기화 | ||
val indices = IntArray(givenSize) | ||
for (i in 0 until givenSize) { | ||
indices[i] = i | ||
} | ||
|
||
while (indices[givenSize - 1] < maxNumber) { | ||
processResult.add(indices.map { nums[it] }.sorted()) | ||
var i = givenSize - 1 | ||
|
||
while (i >= 0 && indices[i] == i + maxNumber - givenSize) { | ||
i-- | ||
} | ||
|
||
if (i >= 0) { | ||
indices[i]++ | ||
for (j in i + 1 until givenSize) { | ||
indices[j] = indices[j-1] + 1 | ||
} | ||
} else break | ||
} | ||
|
||
return processResult.filter { it.sum() == 0 } | ||
} | ||
|
||
/** | ||
* case02. 투 포인터를 사용한 풀이 | ||
* 조합을 사용한 풀이와 달리 시간 초과가 발생하지 않음. O(n^3)의 시간 복잡도를 O(n^2)으로 줄임 | ||
* | ||
* 시간 복잡도: | ||
* -> 주어진 숫자 배열 오름차순으로 정렬: O(nlogn) | ||
* -> 세 개의 숫자를 더하는 로직 | ||
* -> 외부 반복문을 통해 주어진 배열 전체 조회: O(n) | ||
* -> 내부 반복문을 통해 start to last index 순회: O(n) | ||
* -> O(n^2) | ||
* ∴ O(nlogn) + O(n^2) => O(n^2) | ||
* | ||
* 공간 복잡도: | ||
* -> 주어진 숫자 배열의 정렬을 담는 공간 필요: O(n) | ||
*/ | ||
fun threeSum(nums: IntArray): List<List<Int>> { | ||
val processResult = mutableListOf<List<Int>>() | ||
val sortedNums = nums.sorted() | ||
|
||
for (i in sortedNums.indices) { | ||
if (i > 0 && sortedNums[i] == sortedNums[i-1]) continue | ||
|
||
var startIndex = i + 1 | ||
var lastIndex = sortedNums.size - 1 | ||
|
||
while (startIndex < lastIndex) { | ||
val sum = sortedNums[i] + sortedNums[startIndex] + sortedNums[lastIndex] | ||
when { | ||
sum == 0 -> { | ||
processResult.add(listOf(sortedNums[i], sortedNums[startIndex], sortedNums[lastIndex])) | ||
while (startIndex < lastIndex && sortedNums[startIndex] == sortedNums[startIndex + 1]) startIndex++ | ||
while (startIndex < lastIndex && sortedNums[lastIndex] == sortedNums[lastIndex - 1]) lastIndex-- | ||
startIndex++ | ||
lastIndex-- | ||
} | ||
sum < 0 -> { | ||
startIndex++ | ||
} | ||
else -> { | ||
lastIndex-- | ||
} | ||
} | ||
} | ||
} | ||
return processResult | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
class Solution { | ||
public List<List<Integer>> threeSum(int[] nums) { | ||
/** | ||
1. understanding | ||
- 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) | ||
2. solve strategy | ||
- brute force | ||
- in every combination, validate sum of the nums equal to 0 | ||
- 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... | ||
- sort and two pointers | ||
- sort nums in ascending order, so move the left pointer to right means the sum of window is getting bigger. | ||
- and mid pointer set to left + 1 index | ||
- 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. | ||
- [-4, -1, -1, 0, 1, 2]: | ||
3. complexity | ||
- 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. | ||
- space: O(1) -> no extra space is needed | ||
*/ | ||
// 0. assign return variable Set | ||
Set<List<Integer>> answer = new HashSet<>(); | ||
|
||
// 1. sort the num array in ascending order | ||
Arrays.sort(nums); // O(NlogN) | ||
// Arrays.stream(nums).forEach(System.out::println); | ||
|
||
// 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. | ||
for (int left = 0; left < nums.length - 1; left++) { | ||
int mid = left + 1; | ||
int right = nums.length - 1; | ||
while (mid < right) { | ||
// System.out.println(String.format("%d,%d,%d", nums[left], nums[mid], nums[right])); | ||
int sum = nums[left] + nums[mid] + nums[right]; | ||
if (sum > 0) { | ||
right--; | ||
} else if (sum == 0) { | ||
answer.add(List.of(nums[left], nums[mid], nums[right])); | ||
right--; | ||
} else { | ||
mid++; | ||
} | ||
} | ||
} | ||
|
||
return new ArrayList<>(answer); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// 이전에 투포인터를 활용하여 시도했지만 중복된 값들을 처리하는데 어려움이 있었습니다. | ||
// 그래서 해답을 보았고 새로운 방법으로 풀어보았습니다. | ||
// 서로 다른 i와 j 인덱스를 2중 for문으로 진행하면서 | ||
// i와 j사이 수들을 set으로 관리합니다. | ||
// set에 -nums[i]-nums[j]가 존재하면 결과 리스트에 추가합니다. | ||
// 시간복잡도 : O(N^2) | ||
// 공간복잡도 : O(N) | ||
class SolutionGotprgmer { | ||
public List<List<Integer>> threeSum(int[] nums) { | ||
// 결과를 저장할 리스트 | ||
List<List<Integer>> result = new ArrayList<>(); | ||
Set<Integer> set; | ||
Set<List<Integer>> resultSet = new HashSet<>(); | ||
List<Integer> numList; | ||
|
||
|
||
// 리스트 정렬 | ||
Arrays.sort(nums); | ||
for(int i=0;i<nums.length-2;i++){ | ||
if (i > 0 && nums[i - 1] == nums[i]) continue; | ||
|
||
set = new HashSet<>(); | ||
for(int j=i+1;j<nums.length;j++){ | ||
int checkNum = nums[i]+nums[j]; | ||
if(set.contains(-checkNum)){ | ||
numList = new ArrayList<>(Arrays.asList(nums[i], -checkNum, nums[j])); | ||
if(!resultSet.contains(numList)){ | ||
result.add(numList); | ||
resultSet.add(numList); | ||
} | ||
} | ||
set.add(nums[j]); | ||
} | ||
} | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class Solution: | ||
def threeSum(self, nums: List[int]) -> List[List[int]]: | ||
answerSet = set() | ||
nums.sort() | ||
|
||
for i in range(len(nums) - 2): | ||
leftIdx = i + 1 | ||
rightIdx = len(nums) - 1 | ||
while leftIdx < rightIdx: | ||
sum = nums[i] + nums[leftIdx] + nums[rightIdx] | ||
if sum < 0: | ||
leftIdx += 1 | ||
elif sum > 0: | ||
rightIdx -= 1 | ||
else: | ||
answerSet.add((nums[i], nums[leftIdx], nums[rightIdx])) | ||
leftIdx = leftIdx + 1 | ||
rightIdx = rightIdx - 1 | ||
|
||
return list(answerSet) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/** | ||
* @param {number[]} nums | ||
* @return {number[][]} | ||
*/ | ||
|
||
|
||
// Time Complexity: O(n^2) | ||
// Space Complexity: O(n^2) | ||
|
||
var threeSum = function (nums) { | ||
|
||
const sorted = [...nums].sort((a, b) => a - b); | ||
|
||
let result = []; | ||
|
||
// Loop through the array and pick each number as the first number for the triplet | ||
for (let i = 0; i < sorted.length - 2; i++) { | ||
|
||
// skip duplicate values for sorted[middle] | ||
if(i > 0 && sorted[i - 1] === sorted[i]) { | ||
continue; | ||
} | ||
|
||
let left = i + 1; // Left pointer starts right after the current middle | ||
let right = sorted.length - 1; // Right pointer starts at the last element | ||
|
||
while (left < right) { | ||
const sum = sorted[i] + sorted[left] + sorted[right]; | ||
|
||
if (sum === 0) { | ||
result.push([sorted[left], sorted[i], sorted[right]]); | ||
|
||
// skip duplicates for sorted[left] and sorted[right] | ||
while(left < right && sorted[left] === sorted[left + 1]){ | ||
left += 1; // Move left pointer to the right to skip duplicate values | ||
} | ||
|
||
while(left < right && sorted[right] === sorted[right - 1]) { | ||
right -= 1; // Move right pointer to the left to skip duplicate values | ||
} | ||
|
||
left += 1; | ||
right -= 1; | ||
|
||
} else if (sum > 0) { | ||
right -= 1; | ||
|
||
} else { | ||
left += 1 | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
|
||
}; | ||
|
||
|
||
// var threeSum = function (nums) { | ||
|
||
// i != j, i != k, and j != k can be interpreted as i < j < k | ||
|
||
// three nested loops | ||
// time complexity of O(n³) | ||
// Time Limit Exceeded | ||
|
||
// let result = []; | ||
|
||
// for (let i = 0; i < nums.length - 2; i++) { | ||
// for (let j = i + 1; j < nums.length - 1; j++) { | ||
// for (let k = j + 1; k < nums.length; k++) { | ||
// if (nums[i] + nums[j] + nums[k] === 0) { | ||
// const str = [nums[i], nums[j], nums[k]].sort((a, b) => a - b).join(",") | ||
// result.push(str) | ||
// } | ||
// } | ||
// } | ||
|
||
// } | ||
|
||
// result = [... new Set(result)].map(str => str.split(",").map(str => +str)) | ||
|
||
// return result; | ||
|
||
// } | ||
|
Oops, something went wrong.