Skip to content

[jiji-hoon96] WEEK 02 solutions #1202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions 3sum/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* @param {number[]} nums
* @return {number[][]}
*
* 풀이 1
*
* 이렇게 푸니까 시간복잡도 O(n^3) / 공간복잡도 O(n) 라서 복잡한 예시에는 time limit 이 발생함
* 개선해보자..
*
* function threeSum(nums: number[]): number[][] {
* nums.sort((a, b) => a - b);
* let result = []
* for (let i= 0; i<nums.length; i++){
* for(let j= i+1 ; j <nums.length; j++){
* for (let k = j+1; k<nums.length; k++){
* if(nums[i]+nums[j]+nums[k]===0){
* result.push([nums[i], nums[j], nums[k]]);
* }
* }
* }
* }
*
* return Array.from(
* new Set(result.map(item => JSON.stringify(item))),
* str => JSON.parse(str)
* );
* }
*
* 풀이 2
*
* 투포인터를 활용해보자.
* 아래처럼 문제를 풀게되면 시간복잡도 O(n^2) / 공간복잡도 O(1) 이다.
* 시공간 복잡도가 줄긴하지만 메모리 사용량과 큰 숫자를 다룰 때 성능이 매우 좋다!
*/


function threeSum(nums: number[]): number[][] {
let result : number[][] = []
nums.sort((a, b) => a - b);
const n = nums.length;

for(let first = 0; first<n-2; first++){
// 첫번째가 양수면 0이 될 수 없음
if(nums[first] > 0) break;

//중복된 수는 건너뜀
if(first > 0 && nums[first]===nums[first-1]) continue;

let left = first + 1;
let right = n-1;

while(left < right){
const sum = nums[first] +nums[left] + nums[right];

if(sum < 0){
left ++
}else if(sum > 0){
right --;
}else{
result.push([nums[first],nums[left],nums[right]]);
// left, left+1 이 같을 때 중복된 수는 건너뜀
while(left < right && nums[left] === nums[left+1]) left++;
// right, right+1 이 같을 때 중복된 수는 건너뜀
while(left < right && nums[right] === nums[right-1]) right--;
left++;
right--;
}
}
}
return result;
}
37 changes: 37 additions & 0 deletions climbing-stairs/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @param n
*
* dp, 슬라이딩 윈도우 사용해서 풀 수 있다.
*
* 공간 복잡도를 줄이기 위해서 아래와같이 슬라이딩을 활용할 수 있다.
*
* function climbStairs(n: number): number {
* if (n <= 2) return n;
*
* let first = 1; // 1계단을 오르는 방법 수
* let second = 2; // 2계단을 오르는 방법 수
*
* for (let i = 3; i <= n; i++) {
* let current = first + second;
* first = second;
* second = current;
* }
*
* return second;
* }
*/


function climbStairs(n: number): number {
if(n <= 2) return n;

let dp: number[] = new Array(n+1);
dp[1] = 1;
dp[2] = 2;

for(let i=3;i<=n;i++){
dp[i] = dp[i-1] +dp[i-2];
}

return dp[n]
};
44 changes: 44 additions & 0 deletions product-of-array-except-self/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
*
* 풀이 1
*
* 아래와 같이 문제를 푸니, 성능적으로 문제가 발생했다.
* 시간복잡도는 0(n2) / 공간 복잡도는 0(n)
*
* function productExceptSelf(nums: number[]): number[] {
* if(nums.every(num => num === 0)) return nums; 시간 복잡도 0(n)
* if(nums.length > 2 && nums.filter(num=> num ===0).length > 1) return new Array(nums.length).fill(0) 시간 복잡도 0(n) 공간 복잡도 0(n)
* let result = [] 공간 복잡도 0(n)
* for(let i =0;i<nums.length; i++){ 시간 복잡도 0(n)
* let multi = 1;
* const a= nums.filter((num,index)=> index !== i); 시간 복잡도 0(n) 공간 복잡도 0(n)
* for(let item of a){ 시간 복잡도 0(n)
* multi *= item
* }
* result.push(multi)
* }
* return result
* };
*
* 풀이 2 는 누적합 알고리즘을 사용해서 왼쪽 방향에서 시작해 오른쪽 방향으로 곱하는 방식으로 문제 해결
*
*/

function productExceptSelf(nums: number[]): number[] {
const n = nums.length;
const result = new Array(n).fill(1);

let leftProduct = 1;
for (let i = 0; i < n; i++) {
result[i] *= leftProduct;
leftProduct *= nums[i];
}

let rightProduct = 1;
for (let i = n - 1; i >= 0; i--) {
result[i] *= rightProduct;
rightProduct *= nums[i];
}

return result;
}
34 changes: 34 additions & 0 deletions valid-anagram/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
*
* @param s
* @param t
*
* 풀이 1
* s.split("").sort().join("") === t.split("").sort().join("") ? true : false
*
* 시간 복잡도: O(n log n)
* 공간 복잡도: O(n)
*
* 너무 비효율적임.. 문자열을 배열로 바꾸고 다시 배열로 변환하고.. 개선해보자
*
*/

function isAnagram(s: string, t: string): boolean {
if(s.length !== t.length) return false;

// 해시맵 만들어주고
const charCount : Record<string,number> = {};

// 여기서는 늘려주고 O(n)
for(let char of s){
charCount[char] = (charCount[char] || 0) + 1;
}

// 여기는 존재하면 없애주자 O(n)
for(let char of t){
if(!charCount[char]) return false;
charCount[char]--;
}

return true
};
58 changes: 58 additions & 0 deletions validate-binary-search-tree/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*
* 문제가 너무 이해가 안감.. 처음보는 개념 너무 어려움
*
* 우선 이진트리에 대해서 공부해보기 위해서 https://www.youtube.com/watch?v=i57ZGhOVPcI 을 살펴보았음
*
* 풀이 1
*
* 재귀적 깊이 우선 탐색(DFS) 방식으로 해결 (메모리 효율성 미세하게 좋음) => 이 방법이 이진트리 개념에 조금 더 직관적임
*
* function isValidBST(root: TreeNode | null): boolean {
* function validate(node: TreeNode | null, min: number | null, max: number | null): boolean {
* if (node === null) return true;
*
* if ((min !== null && node.val <= min) || (max !== null && node.val >= max)) {
* return false;
* }
*
* return validate(node.left, min, node.val) && validate(node.right, node.val, max);
* }
*
* return validate(root, null, null);
* }
*
* 풀이 2
*
* 중위 순회 방법을 활용해보기 => 코드는 이 방법이 더 쉽고 이해하기 좋음
*/

function isValidBST(root: TreeNode | null): boolean {
let prev: number | null = null;

function inorder(node: TreeNode | null): boolean {
if (node === null) return true;

if (!inorder(node.left)) return false;

if (prev !== null && node.val <= prev) {
return false;
}
prev = node.val;

return inorder(node.right);
}

return inorder(root);
}