Skip to content

[mallayon] Week 8 #967

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 6 commits into from
Feb 1, 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
48 changes: 48 additions & 0 deletions clone-graph/mmyeon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
class _Node {
val: number;
neighbors: _Node[];
constructor(val?: number, neighbors?: _Node[]) {
this.val = val === undefined ? 0 : val;
this.neighbors = neighbors === undefined ? [] : neighbors;
}
}

/**
* @link https://leetcode.com/problems/clone-graph/description/
*
* 접근 방법 :
* - 엣지 케이스 : 주어진 노드가 null이면 그대로 리턴
* - 이미 방문한 노드인지 확인 : 방문한 노드인 경우, 저장된 복사 노드 리턴해서 중복 생성 방지
* - 새로운 노드 클론하고 visited 맵에 저장
* - 해당 노드의 이웃 노드도 순회하면서 복제
* - 클론된 노드 리턴
*
* 시간복잡도 : O(n + e)
* - n은 노드의 개수, e는 노드 연결하는 엣지의 개수
* - 모든 노드 순회하면서 각 노드의 이웃 탐색
*
* 공간복잡도 : O(n)
* - 모든 노드를 클론해서 visited 맵에 저장되므로 O(n)
* - 그래프가 선형 구조인 최악의 경우, 재귀 호출 스택이 O(n)
*/
function cloneGraph(node: _Node | null): _Node | null {
if (!node) return null;
const visited = new Map<number, _Node>();

const cloneNode = (node: _Node): _Node => {
if (visited.has(node.val)) return visited.get(node.val) as _Node;

const clonedNode = new _Node(node.val);
visited.set(node.val, clonedNode);

for (const neighbor of node.neighbors) {
const clonedNeighbor = cloneNode(neighbor);

clonedNode.neighbors.push(clonedNeighbor);
}

return clonedNode;
};

return cloneNode(node);
}
31 changes: 31 additions & 0 deletions longest-common-subsequence/mmyeon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @link https://leetcode.com/problems/longest-common-subsequence/description/
*
* 접근 방법 :
* - LCS 길이 담을 DP 배열 선언
* - 문자 순회하면서 같은 문자인 경우, 이전 값 + 1 로 업데이트
* - 문자 다른 경우, 이전 값 그대로 유지
*
* 시간복잡도 : O(m * n)
* - 두 문자열 길이 크기만큼 이중 반복문 실행
*
* 공간복잡도 : O(m * n)
* - 두 문자 길이 크기만큼 DP 배열에 저장
*/
function longestCommonSubsequence(text1: string, text2: string): number {
const m = text1.length,
n = text2.length;

const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));

for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (text1[i - 1] === text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}
39 changes: 39 additions & 0 deletions longest-repeating-character-replacement/mmyeon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @link https://leetcode.com/problems/longest-repeating-character-replacement/
*
* 접근 방법 :
* - 문자열 순회하면서, 현재 윈도우 내 문자의 빈도수 저장
* - 윈도우 축소 조건 : 윈도우 크기 - 윈도우 내 최다 등장 문자의 개수 > k
* => k보다 다른 문자의 개수가 많은 경우, left 포인터 이동해서 윈도우 크기 줄이기
* - 윈도우 크기 조절하면서 최대 길이 업데이트
*
* 시간복잡도 : O(n)
* - 문자 n개만큼 1회 순회하면서 윈도우 크기 조절
*
* 공간복잡도 : O(1)
* - 대문자의 개수(26개)만큼 map에 저장
*/
function characterReplacement(s: string, k: number): number {
const map = new Map<string, number>();
let maxFrequency = 0,
maxLength = 0,
left = 0;

for (let right = 0; right < s.length; right++) {
const rightPositionChar = s[right];
// 문자의 빈도수 map에 저장
map.set(rightPositionChar, (map.get(rightPositionChar) ?? 0) + 1);
maxFrequency = Math.max(maxFrequency, map.get(rightPositionChar)!);

// 윈도우 축소해야 되는 경우 - k보다 다른 문자의 개수가 많은 경우
if (right - left + 1 - maxFrequency > k) {
map.set(s[left], map.get(s[left])! - 1);
left++;
}
Comment on lines +29 to +32
Copy link
Contributor

Choose a reason for hiding this comment

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

슬라이딩 윈도우가 잘 사용 포인트네요 :)


// 최대 길이 업데이트
maxLength = Math.max(maxLength, right - left + 1);
}

return maxLength;
}
38 changes: 38 additions & 0 deletions number-of-1-bits/mmyeon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* @link https://leetcode.com/problems/number-of-1-bits/description/
*
* 접근 방법 :
* - n을 2로 나누면서 나머지가 1인 경우 카운트를 업데이트한다.
*
* 시간복잡도 : O(logn)
* - 숫자의 비트 길이만큼 반복
*
* 공간복잡도 : O(1)
* - 고정된 변수만 사용
*/
function hammingWeight(n: number): number {
let bitCount = 0;
while (n >= 1) {
bitCount += n % 2;

n = Math.floor(n / 2);
}

return bitCount;
}

/**
* 접근 방법 : 비트 연산자 활용
* - n & 1 : n의 마지막 비트가 1인지 확인하여 bitCount 업데이트
* - n >>>= 1 : 오른쪽 시프트로 n을 1비트씩 이동
*/
function hammingWeight(n: number): number {
let bitCount = 0;
while (n >= 1) {
bitCount += n & 1;

n >>>= 1;
}

return bitCount;
}
29 changes: 29 additions & 0 deletions sum-of-two-integers/mmyeon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
*@link https://leetcode.com/problems/sum-of-two-integers/description/
*
* 접근 방법 :
* - 비트 AND 연산자(&) 사용해서 자리 올림이 필요한 비트 계산하고 왼쪽 시프트(<<)로 자리 올림값을 다음 자리로 이동
* - 비트 XOR 연산자(^) 사용해서 자리 올림 제외한 자리합 계산하고 a값 업데이트
* - 자리 올림값이 0이 될 때까지 자리 올림 반복
* - 자리 올림 없으면 최종합이 저장된 a 리턴
*
*
* 시간복잡도 : O(k)
* - k는 숫자의 비트 수, 최대 k번 반복
*
* 공간복잡도 : O(1)
* - 고정된 변수만 사용
*
*/

function getSum(a: number, b: number): number {
while (b) {
// 자리 올림 계산
const carry = (a & b) << 1;
// 자리합 업데이트 (같은 비트 = 0, 다른 비트 = 1)
a ^= b;
b = carry;
}

return a;
}