Skip to content
Open
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: 0 additions & 71 deletions 3sum/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,71 +0,0 @@
/**
* @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;
}
23 changes: 0 additions & 23 deletions best-time-to-buy-and-sell-stock/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,23 +0,0 @@
function maxProfit(prices: number[]): number {
if (prices.length <= 1) return 0;

let minPrice = prices[0];
let maxProfit = 0;

for (let i = 1; i < prices.length; i++) {
// 현재 가격이 최소가보다 낮으면 최소가 업데이트
if (prices[i] < minPrice) {
minPrice = prices[i];
}
// 현재 가격으로 팔았을 때의 이익 계산
else {
const currentProfit = prices[i] - minPrice;
// 최대 이익 업데이트
if (currentProfit > maxProfit) {
maxProfit = currentProfit;
}
}
}

return maxProfit;
}
37 changes: 0 additions & 37 deletions climbing-stairs/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,37 +0,0 @@
/**
* @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]
};
49 changes: 0 additions & 49 deletions combination-sum/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,49 +0,0 @@
/**
*
* @param candidates
* @param target
*
* backtracking 알고리즘으로 문제 해결
*
*/

function combinationSum(candidates: number[], target: number): number[][] {
const result : number[][] = [];
if(candidates.length === 0){
return result ;
}

candidates.sort((a,b)=> a-b);

const validCandidates : number[] = candidates.filter(num => num <= target);

if(validCandidates.length ===0) {
return result;
}

const currentCombination : number[] = [];

function backtrack (startIndex : number, remainingTarget : number) :void {
if(remainingTarget === 0){
result.push([...currentCombination]);
return;
}

for(let i=startIndex; i<validCandidates.length; i++){
const currentNum = validCandidates[i];

if(currentNum > remainingTarget) {
break;
}
currentCombination.push(currentNum);

backtrack(i,remainingTarget - currentNum)

currentCombination.pop()

}
}

backtrack(0, target);
return result;
};
18 changes: 8 additions & 10 deletions contains-duplicate/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
/**
* 배열에 중복된 요소가 있는지 확인하는 함수
* @param nums - 확인할 정수 배열
* @returns 중복된 요소가 있으면 true, 모든 요소가 고유하면 false
*
* 기존에 for문을 사용해 filter,indexOf 방식을 사용했지만, 시간복잡도가 O(n^2)이라서 시간초과가 발생했다.
* Set을 사용하면 중복된 요소를 제거하고, size를 통해 중복된 요소가 있는지 확인할 수 있다.
*/
function containsDuplicate(nums: number[]): boolean {
return new Set(nums).size !== nums.length
};
let result = false;
if (nums.length !== new Set(nums).size) result = true;

return result;
}

containsDuplicate([1, 2, 3, 1]); //true
containsDuplicate([1, 1, 1, 3, 3, 4, 3, 2, 4, 2]); //true
35 changes: 0 additions & 35 deletions decode-ways/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,35 +0,0 @@
function numDecodings(s: string): number {
// 빈 문자열이거나 0으로 시작하면 디코딩 불가
if (!s || s[0] === '0') return 0;

const n = s.length;

// 문자열 길이가 1이면 바로 결과 반환
if (n === 1) return 1;

// 초기 상태
let prev = 1; // dp[0]
let curr = s[0] === '0' ? 0 : 1; // dp[1]

for (let i = 2; i <= n; i++) {
let temp = 0;
const oneDigit = parseInt(s[i - 1]);
const twoDigit = parseInt(s[i - 2] + s[i - 1]);

// 한 자리 숫자로 디코딩 (1-9)
if (oneDigit >= 1) {
temp += curr;
}

// 두 자리 숫자로 디코딩 (10-26)
if (twoDigit >= 10 && twoDigit <= 26) {
temp += prev;
}

// 상태 업데이트
prev = curr;
curr = temp;
}

return curr;
}
38 changes: 13 additions & 25 deletions house-robber/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
/**
*
* @param {number[]} nums
* @param nums
*
* 풀이
* dp 배열을 사용해 nums 배열의 길이만큼 초기화한다.
* dp[0]은 nums[0]으로 초기화하고, dp[1]은 nums[0]과 nums[1] 중 큰 값으로 초기화한다.
* dp[2]부터는 dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i])로 초기화한다.
* dp[i-1]은 i번째 집을 털지 않은 경우, dp[i-2] + nums[i]는 i번째 집을 털고 i-1번째 집을 털지 않은 경우이다.
*
*/

function rob(nums: number[]): number {
const n = nums.length
if(n===0) return 0
if(n===1) return nums[0];
let take = 0;
let skip = 0;

for (const num of nums) {
const nextTake = skip + num;
const nextSkip = Math.max(take, skip);

let dp0 = nums[0]
let dp1 = Math.max(nums[0], nums[1]);
take = nextTake;
skip = nextSkip;
}

for(let i=2;i<n;i++){
const curMaxValue = Math.max(dp1, dp0 + nums[i]);
dp0 = dp1;
dp1 = curMaxValue;
}
return Math.max(take, skip);
}

return dp1
};
rob([1, 2, 3, 1]); // 4
rob([2, 7, 9, 3, 1]); // 12
46 changes: 19 additions & 27 deletions longest-consecutive-sequence/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
/**
* 연속된 숫자의 최대 길이를 구하는 문제
* @param {number[]} nums
* @return {number}
*
* 풀이
*
* nums 배열을 중복을 제거하고 오름차순으로 정렬한다.
* 중복을 제거하고 정렬한 배열을 순회하면서 연속된 숫자의 길이를 구한다.
*/
function longestConsecutive(nums: number[]): number {
if (nums.length === 0) return 0;
const sortedNums = Array.from(new Set(nums)).sort((a, b) => a - b);
let result = 0;
if (nums.length === 0) return result;

if (sortedNums.length === 1) return 1;
const no_duplicate = [...new Set(nums)].sort((a, b) => a - b);
let count = 1;

let currentCount = 1;
let maxCount = 1;

for(let i = 0; i < sortedNums.length - 1; i++) {
const currentNum = sortedNums[i];
const nextNum = sortedNums[i + 1];

if(currentNum + 1 === nextNum) {
currentCount++;
maxCount = Math.max(maxCount, currentCount);
} else {
currentCount = 1;
}
for (let i = 0; i < no_duplicate.length; i++) {
if (no_duplicate[i + 1] - no_duplicate[i] === 1) {
count++;
} else {
result = Math.max(result, count);
count = 1;
}
}

return maxCount;
result = Math.max(result, count);
return result;
}

longestConsecutive([0, 3, 7, 2, 5, 8, 4, 6, 0, 1]); //9
longestConsecutive([100, 4, 200, 1, 3, 2]); //4
longestConsecutive([1, 0, 1, 2]); //3
longestConsecutive([]); //0
longestConsecutive([1, 2, 6, 7, 8]); //3
29 changes: 0 additions & 29 deletions maximum-depth-of-binary-tree/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,29 +0,0 @@
/**
* 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)
* }
* }
*/

function maxDepth(root: TreeNode | null): number {
// 기본 케이스: 노드가 없는 경우 깊이는 0
if (root === null) {
return 0;
}

// 왼쪽 서브트리의 최대 깊이
const leftDepth = maxDepth(root.left);

// 오른쪽 서브트리의 최대 깊이
const rightDepth = maxDepth(root.right);

// 현재 노드의 깊이는 왼쪽과 오른쪽 서브트리 중 더 깊은 것에 1을 더한 값
return Math.max(leftDepth, rightDepth) + 1;
}
20 changes: 0 additions & 20 deletions maximum-subarray/jiji-hoon96.ts
Original file line number Diff line number Diff line change
@@ -1,20 +0,0 @@
function maxSubArray(nums: number[]): number {
// 배열이 비어 있는 경우 체크 (제약조건에 의해 발생하지 않지만, 견고한 코드를 위해)
if (nums.length === 0) return 0;

// 현재 부분 배열의 합과 전체 최대 부분 배열 합 초기화
let currentSum = nums[0];
let maxSum = nums[0];

// 두 번째 요소부터 순회
for (let i = 1; i < nums.length; i++) {
// 현재 위치에서의 최대 부분 배열 합 계산
// "이전까지의 합 + 현재 요소" vs "현재 요소부터 새로 시작"
currentSum = Math.max(nums[i], currentSum + nums[i]);

// 전체 최대값 업데이트
maxSum = Math.max(maxSum, currentSum);
}

return maxSum;
}
Loading