diff --git a/3sum/Baekwangho.ts b/3sum/Baekwangho.ts new file mode 100644 index 0000000000..a929405ca7 --- /dev/null +++ b/3sum/Baekwangho.ts @@ -0,0 +1,146 @@ +/** +합산이 0이 되는 서로소 조합을 찾아야 한다.. 좌표가 다른 같은 값은 허용하되, +같은 수로 구성된 조합은 중복을 불허한다. + +기본적으로 3가지 수를 중복없이 조합해서 뽑은 다음, 정렬을 사용하여 set 으로 구분할 수 있지 않을까? + + +function threeSum(nums: number[]): number[][] { + const arraySet = new Set(); + + for (let i = 0; i <= nums.length - 3; i++) { + for (let j = i + 1; j <= nums.length - 2; j++) { + for (let k = j + 1; k <= nums.length - 1; k++) { + if (nums[i] + nums[j] + nums[k] === 0) { + const sorted = [nums[i], nums[j], nums[k]]; + sorted.sort((a, b) => a - b); + const string = sorted.join("#"); + arraySet.add(string); + } + } + } + } + + return Array.from(arraySet).map((el) => + el.split("#").map((el) => Number(el)) + ); +} + */ + +/** +시간 초과해버렸다. 어떻게 효율적으로 풀 수 있을까? +two sum 을 보니 해시테이블을 쓴다고 한다. nums 를 해시테이블로 변환하고, +이중 반복문에서 이를 활용해보자. + +function threeSum(nums: number[]): number[][] { + const arraySet = new Set(); + const hash = new Map(); + nums.forEach((val, idx) => { + const idxes = hash.get(val); + if (idxes && idxes.length) { + hash.set(val, [...idxes, idx]); + } else { + hash.set(val, [idx]); + } + }); + + for (let i = 0; i < nums.length - 2; i++) { + for (let j = i + 1; j < nums.length - 1; j++) { + const idxes = hash.get(0 - (nums[i] + nums[j])); + + idxes?.forEach((idx) => { + if (idx != i && idx != j) { + const sorted = [nums[i], nums[j], nums[idx]]; + sorted.sort((a, b) => a - b); + const string = sorted.join("#"); + arraySet.add(string); + } + }); + } + } + + return Array.from(arraySet).map((el) => + el.split("#").map((el) => Number(el)) + ); +} + + */ + +/** +... 0으로만 가득찬 배열에서 time limit 이 발생했다. +풀이를 보고오니, 위 로직에서 0으로 가득찬 arraySet 을 순회하는 곳에서 결국 O(n^3) 이 되어버린다는 점을 확인할 수 있었다. +확실한 것은, 정렬을 추가했을 경우 위 로직도 통과 가능한 정도로 만들어볼 수 있지 않을까 싶었다. + +function threeSum(nums: number[]): number[][] { + nums.sort((a, b) => a - b); + const arraySet = new Set(); + const hash = new Map(); + + nums.forEach((val, idx) => { + const idxes = hash.get(val); + if (idxes && idxes.length) { + hash.set(val, [...idxes, idx]); + } else { + hash.set(val, [idx]); + } + }); + + for (let i = 0; i < nums.length - 2; i++) { + for (let j = i + 1; j < nums.length - 1; j++) { + const idxes = hash.get(0 - (nums[i] + nums[j])) ?? []; + + for (let k = 0; k < idxes.length; k++) { + const idx = idxes[k]; + if (idx != i && idx != j) { + const sorted = [nums[i], nums[j], nums[idx]]; + sorted.sort((a, b) => a - b); + const string = sorted.join("#"); + arraySet.add(string); + + break; + } + } + } + } + + return Array.from(arraySet).map((el) => + el.split("#").map((el) => Number(el)) + ); +} + +근데 어떻게든 못만듦. + */ + +/** +어제 해답을 보았으니, 다시한번 풀어보자. +핵심은 투 포인터를 사용하는 것, 자료구조에 얽메이지 않는 것 + */ + +function threeSum(nums: number[]): number[][] { + nums.sort((a, b) => a - b); + const results = []; + + // [-4, -1, -1, 0, 1, 2] + for (let i = 0; i < nums.length; i++) { + while (nums[i - 1] === nums[i]) i++; + + let low = i + 1; + let high = nums.length - 1; + while (low < high) { + const sum = nums[i] + nums[low] + nums[high]; + if (sum < 0) { + low++; + } else if (sum > 0) { + high--; + } else { + while (nums[high] === nums[high - 1]) high--; + while (nums[low] === nums[low + 1]) low++; + results.push([nums[i], nums[low], nums[high]]); + low++; + high--; + } + } + } + + return results; +} diff --git a/climbing-stairs/Baekwangho.ts b/climbing-stairs/Baekwangho.ts new file mode 100644 index 0000000000..ca5f0c4f73 --- /dev/null +++ b/climbing-stairs/Baekwangho.ts @@ -0,0 +1,44 @@ +/** +4와 5를 각각 구하면 + +1+1+1+1 +1+1+2 +1+2+1 +2+1+1 +2+2 +=> 5 + +1+1+1+1+1 +1+1+1+2 +1+1+2+1 +1+2+1+1 +2+1+1+1 +1+2+2 +2+1+2 +2+2+1 +=> 8 + +왜 피보나치 수열 같을까? 일단 그렇게 값을 계산해보자. + +시간 복잡도: O(n) +공간 복잡도: O(n) + +근데 왜 피보나치인지는 생각해보고 업데이트 하기.. +*/ + +function climbStairs(n: number): number { + if (n === 1) { + return 1; + } + + if (n === 2) { + return 2; + } + + const results = [1, 2]; + for (let i = 2; i < n; i++) { + results.push(results[i - 2] + results[i - 1]); + } + + return results.pop() as number; +} diff --git a/product-of-array-except-self/Baekwangho.ts b/product-of-array-except-self/Baekwangho.ts new file mode 100644 index 0000000000..ff16c9f16c --- /dev/null +++ b/product-of-array-except-self/Baekwangho.ts @@ -0,0 +1,66 @@ +/** +[첫번째 시도] +O(n)의 시간 복잡도로, i 번째 수를 제외한 제곱 수 합을 구하는 문제 +nums 를 좌우에서 순회하며, result += nums[i]^2 or nums[n-i]^2 를 이어 나가되, +두 배열을 더하는 시점에서 nums 의 배열 값을 뺴주면? + +... 문제를 잘못 이해해서 합인 줄 알았다.. 곱이구나 나눗셈 없이 이를 어떻게 구한담 + +일단 nums 에 0이 두개 있으면 정답 배열의 모든 수는 0이다. +그 외에는 곱셈을 유지해야 하는데.. + +두 배열을 만들어서, 전체 수 곱 행렬을 만들어 보자 => 실패 + +수식으로 나타내보면? + +f(n) = n번째 수 제외 전체 곱 +f(0) = f(1) * ... * f(n) +f(1) = f(0) * f(2) * ... * f(n) +f(n-1) = f(0) * ... * f(n-2) * f(n) + +모르겠다.. 오늘은 해설 보고 내일 기억해서 풀어보자 +function productExceptSelf(nums: number[]): number[] { + const forward = [nums[0]]; + const backward = [nums[nums.length - 1]]; + + for (let i = 1; i < nums.length; i++) { + forward.push(forward[i - 1] * nums[i]); + backward.push(backward[i - 1] * nums[nums.length - 1 - i]); + } + + const result = []; + for (let i = 0; i < nums.length - 1; i++) { + result.push(forward[i] * backward[i]); + } + + return result; +} + + */ +/** +[두번째 시도] +접근은 맞았다. 결국 제대로 수식을 작성해야 하는 듯 +수식을 작성해보면, +forward 는 [1, 2, 2*3, 2*3*4] +backward 는 [3*4*5, 4*5, 5, 1] 가 나와야 한다. + +시간 복잡도: O(2n) +공간 복잡도: O(3n) +*/ + +function productExceptSelf(nums: number[]): number[] { + const forward = [1] + const backward = [1] + for (let i=0; i(); + for (let i = 0; i < s.length; i++) { + const value = wordMap.get(s[i]) + if (value) { + wordMap.set(s[i], value + 1); + } else { + wordMap.set(s[i], 1); + } + } + + for (let i = 0; i < t.length; i++) { + const remainWord = wordMap.get(t[i]); + if (remainWord) { + + if (remainWord > 1) { + wordMap.set(t[i], remainWord - 1); + } else if (remainWord === 1) { + wordMap.delete(t[i]); + } + } else { + return false; + } + } + + return wordMap.size === 0 ? true : false; +}