Skip to content

[Jeehay28] WEEK 03 solutions #1283

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 5 commits into from
Apr 19, 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
82 changes: 82 additions & 0 deletions combination-sum/Jeehay28.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Approach 2: Dynamic Programming
// ✅ Time Complexity: O(N * T * K)
// ✅ Space Complexity: O(T * K)
// N = Number of candidates, T = target, K = average number of combination for each dp[i]

function combinationSum(candidates: number[], target: number): number[][] {
// candidates = [2, 3]
// target = 5
// dp = [
// [[]], // dp[0]
// [], // dp[1]
// [[2]], // dp[2]
// [], // dp[3]
// [[2, 2]], // dp[4]
// [] // dp[5]
// ];

// dp = [
// [[]], // dp[0]
// [], // dp[1]
// [[2]], // dp[2]
// [[3]], // dp[3]
// [[2, 2]], // dp[4]
// [[2, 3]] // dp[5]
// ];

const dp: number[][][] = Array.from({ length: target + 1 }, () => []);
// each element in dp is an independent array, and modifying one will not affect others.
dp[0] = [[]];

for (const candidate of candidates) {
for (let num = candidate; num <= target; num++) {
for (const combination of dp[num - candidate]) {
dp[num].push([...combination, candidate]);
}
}
}

return dp[target];
}

// Approach 1: DFS + Backtracking (Recursive)
// ✅ Time Complexity: O(N^(T / min))
// ✅ Space Complexity: O(K + target / min)
// If target = 7 and smallest number is 2, recursion can go up to 7 / 2 = levels deep
// N = number of candidates, T = target value, K = total number of valid combination found

// function combinationSum(candidates: number[], target: number): number[][] {
// // input:
// // 1) an array of distinct integers
// // 2) a target integer

// // output:
// // a list of all unique combinations of candinates where the chosen numbers sum to target(in any order)
// // duplicated numbers allowed

// let result: number[][] = [];
// let nums: number[] = [];

// const dfs = (start: number, total: number) => {
// if (total > target) {
// return;
// }

// if (total === target) {
// result.push([...nums]);
// return;
// }

// for (let i = start; i < candidates.length; i++) {
// if (total + nums[i] <= target) {
// nums.push(candidates[i]);
// dfs(i, total + candidates[i]);
// nums.pop(); // backtrack
// }
// }
// };

// dfs(0, 0);

// return result;
// }
117 changes: 117 additions & 0 deletions decode-ways/Jeehay28.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Approach 4:
// Time Complexity: O(n)
// ✅ Space Complexity: O(1)

function numDecodings(s: string): number {
// s: 2 2 6
// dp: ? ? 1
// cur nxt

let next = 0,
current = 1;

for (let start = s.length - 1; start >= 0; start--) {
const temp = current;

if (s[start] === "0") {
// dp[start] = 0
current = 0;
next = temp;
} else if (
start + 1 < s.length &&
parseInt(s.substring(start, start + 2)) < 27
) {
// dp[start] = dp[start + 1] + dp[start + 2]
current = current + next;
next = temp;
} else {
// dp[start] = dp[start + 1]
next = temp;
}
}
return current;
}


// Approach 3: Dynamic Programming
// Time Complexity: O(n)
// Space Complexity: O(n)

// function numDecodings(s: string): number {
// // 12
// // dp 001
// // 211

// // 226
// // dp 0001
// // 3211

// const dp = Array.from({ length: s.length + 1 }, (el) => 0);
// dp[dp.length - 1] = 1;

// for (let start = s.length - 1; start >= 0; start--) {
// if (s[start] === "0") {
// dp[start] = 0;
// } else if (
// start + 1 < s.length &&
// parseInt(s.substring(start, start + 2)) < 27
// ) {
// dp[start] = dp[start + 1] + dp[start + 2];
// } else {
// dp[start] = dp[start + 1];
// }
// }

// return dp[0];
// }


// Approach 2
// ✅ Time Complexity: O(2^n) -> O(n)
// Space Complexity: O(n)

// function numDecodings(s: string): number {
// const memo = new Map<number, number>();
// memo.set(s.length, 1);

// const dfs = (start: number) => {
// if (memo.has(start)) return memo.get(start);
// if (s[start] === "0") {
// memo.set(start, 0);
// } else if (
// start + 1 < s.length &&
// parseInt(s.substring(start, start + 2)) < 27
// ) {
// memo.set(start, dfs(start + 1)! + dfs(start + 2)!);
// } else {
// memo.set(start, dfs(start + 1)!);
// }
// return memo.get(start);
// };
// return dfs(0)!;
// }


// Approach 1
// ❌ Time Limit Exceeded!
// Time Complexity: O(2^n), where n = s.length
// Space Compexity: O(n), due to recursive call stack
// function numDecodings(s: string): number {
// const dfs = (start: number) => {
// if (start === s.length) {
// return 1;
// }

// if (s[start] === "0") {
// return 0;
// }

// if (start + 1 < s.length && parseInt(s.substring(start, start + 2)) < 27) {
// return dfs(start + 1) + dfs(start + 2);
// } else {
// return dfs(start + 1);
// }
// };

// return dfs(0);
// }
16 changes: 16 additions & 0 deletions maximum-subarray/Jeehay28.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Approach 1:
// Time Complexity: O(n)
// Space Complexity: O(1)

function maxSubArray(nums: number[]): number {
let currentSum = nums[0];
let maxSum = nums[0];

for (let i = 1; i < nums.length; i++) {
currentSum = Math.max(nums[i], currentSum + nums[i]);
maxSum = Math.max(currentSum, maxSum);
}

return maxSum;
}

50 changes: 50 additions & 0 deletions number-of-1-bits/Jeehay28.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Approach 2
// 🗓️ 2025-04-15
// ⏳ Time Complexity: O(log n)
// 💾 Space Complexity: O(1)

function hammingWeight(n: number): number {
// n(이진수) & 1 -> 1: 이진수 n의 마지막 비트가 1인 경우에만 1 반환
// n(이진수) >> 1: 마지막 비트 제거
// 🔍 In binary numbers:
// Decimal: 11
// Binary: 1 0 1 1
// ↑ ↑
// MSB LSB
// (Most Sig.) (Least Sig.)
// n & 1: only checks the least significant bit (LSB), if the LSB is 1, the result is 1.
// n >>= 1: Each bit is moved one place to the right.

let count = 0;

while (n) {
count += n & 1; // add 1 if the least significant bit of n is 1
n >>= 1; // The LSB is removed (dropped).
}

return count;
}


// Approach 1
// 🗓️ 2025-04-15
// ⏳ Time Complexity: O(log n)
// 💾 Space Complexity: O(1)

// function hammingWeight(n: number): number {
// // input: a positive number n
// // output: the number of set bits in binary representation
// // set bits: a bit in the binary representaton of a number that has a value of 1
// // 11 -> 1011 -> 3

// let cnt = 0;
// while (n > 0) {
// if (n % 2 === 1) {
// cnt += 1;
// }
// n = Math.floor(n / 2);
// }

// return cnt;
// }

55 changes: 55 additions & 0 deletions valid-palindrome/Jeehay28.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Approach 2
// 🗓️ 2025-04-14
// ⏳ Time Complexity: O(n)
// 💾 Space Complexity: O(1)

function isPalindrome(s: string): boolean {
let low = 0, high = s.length - 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

투포인터 방식을 사용하신건가요?! 이렇게 접근도 가능하군요..!

const reg = /[0-9a-zA-Z]/;

while (low < high) {
while (low < high && !reg.test(s[low])) {
low += 1;
}

while (low < high && !reg.test(s[high])) {
high -= 1;
}

if (s[low].toLowerCase() !== s[high].toLowerCase()) {
return false;
}
low += 1;
high -= 1;
}

return true;
}


// Approach 1
// 🗓️ 2025-04-14
// ⏳ Time Complexity: O(n)
// 💾 Space Complexity: O(n)

// function isPalindrome(s: string): boolean {
// // cover all uppercase letters into lowercasse letters
// // remove all non-alphanumeric characters (letters and numbers)
// // it reads the same forward and backward

// const cleaned = s.toLowerCase().match(/[0-9a-z]/g);

// // Converting to lowercase (toLowerCase()): O(n), where n is the length of the string
// // Matching with regex (match(/[0-9a-z]/g)): O(n), where n is the length of the string, as the regex engine needs to check each character in the string
// // join("") operation: O(m), where m is the length of the cleaned array.
// // reverse() operation: O(m), where m is the length of the cleaned array.
// // Comparison (s_forward === s_backward): O(n) because it checks each character one by one

// if (cleaned !== null) {
// const s_forward = cleaned.join("");
// const s_backward = cleaned.reverse().join("");
// return s_forward === s_backward;
// } else {
// return true;
// }
// }