Skip to content

Commit 76fe4b5

Browse files
authored
Merge pull request #500 from wogha95/main
[재호] WEEK 08 Solutions
2 parents 3889d5e + 48be0f5 commit 76fe4b5

File tree

5 files changed

+259
-0
lines changed

5 files changed

+259
-0
lines changed

clone-graph/wogha95.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* TC: O(V + E)
3+
* 모든 정점를 방문하게 되고
4+
* 방문한 정점에서 연결된 간선을 queue에 추가하는 반복문을 실행합니다.
5+
* 따라서 시간복잡도는 정점 + 간선에 선형적으로 비례합니다.
6+
*
7+
* SC: O(V + E)
8+
* memory, visitedNodeVal 에서 V만큼 데이터 공간을 가집니다.
9+
* 그리고 queue에서 최대 모든 간선 갯수 * 2 만큼 갖게 됩니다.
10+
* 따라서 O(V + 2E) = O(V + E)로 계산했습니다.
11+
*
12+
* V: vertex, E: edge
13+
*/
14+
15+
/**
16+
* // Definition for a _Node.
17+
* function _Node(val, neighbors) {
18+
* this.val = val === undefined ? 0 : val;
19+
* this.neighbors = neighbors === undefined ? [] : neighbors;
20+
* };
21+
*/
22+
23+
/**
24+
* @param {_Node} node
25+
* @return {_Node}
26+
*/
27+
var cloneGraph = function (node) {
28+
if (!node) {
29+
return null;
30+
}
31+
32+
const memory = new Map();
33+
const visitedNodeVal = new Set();
34+
35+
return bfsClone(node);
36+
37+
// 1. bfs로 순회하면서 deep clone한 graph의 head를 반환
38+
function bfsClone(start) {
39+
const queue = [start];
40+
const clonedHeadNode = new _Node(start.val);
41+
memory.set(start.val, clonedHeadNode);
42+
43+
while (queue.length > 0) {
44+
const current = queue.shift();
45+
if (visitedNodeVal.has(current.val)) {
46+
continue;
47+
}
48+
49+
const clonedCurrentNode = getCloneNode(current.val);
50+
51+
for (const neighbor of current.neighbors) {
52+
const clonedNeighborNode = getCloneNode(neighbor.val);
53+
clonedCurrentNode.neighbors.push(clonedNeighborNode);
54+
55+
queue.push(neighbor);
56+
}
57+
58+
visitedNodeVal.add(current.val);
59+
}
60+
61+
return clonedHeadNode;
62+
}
63+
64+
// 2. memory에 val에 해당하는 node 반환 (없을 경우 생성)
65+
function getCloneNode(val) {
66+
if (!memory.has(val)) {
67+
const node = new _Node(val);
68+
memory.set(val, node);
69+
return node;
70+
}
71+
72+
return memory.get(val);
73+
}
74+
};

longest-common-subsequence/wogha95.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* 알고달레 풀이 참고해서 풀었습니다.
3+
* @see https://www.algodale.com/problems/longest-common-subsequence/
4+
*
5+
* DP + 2차원 배열을 이용한 풀이
6+
* 행은 text1, 열은 text2에 대응하고
7+
* index는 text의 처음부터 몇개 문자를 사용할건지 의미합니다.
8+
* 마지막 문자가 동일하다면 dp[index1][index2] = dp[index1 - 1][index2 - 1] + 1
9+
* 마지막 문자가 다르다면 dp[index1][index2] = Math.max(dp[index1 - 1][index2], dp[index1][index2 - 1])
10+
*
11+
* TC: O(T1 * T2)
12+
* 2차원 배열을 순회
13+
*
14+
* SC: O(T1 * T2)
15+
* 2차원 배열 생성
16+
*
17+
* T1: text1.length, T2: text2.length
18+
*/
19+
20+
/**
21+
* @param {string} text1
22+
* @param {string} text2
23+
* @return {number}
24+
*/
25+
var longestCommonSubsequence = function (text1, text2) {
26+
const LENGTH1 = text1.length;
27+
const LENGTH2 = text2.length;
28+
const memory = Array.from({ length: LENGTH1 + 1 }, () =>
29+
Array.from({ length: LENGTH2 + 1 }, () => 0)
30+
);
31+
32+
for (let index1 = 1; index1 <= LENGTH1; index1++) {
33+
for (let index2 = 1; index2 <= LENGTH2; index2++) {
34+
if (text1[index1 - 1] === text2[index2 - 1]) {
35+
memory[index1][index2] = memory[index1 - 1][index2 - 1] + 1;
36+
} else {
37+
memory[index1][index2] = Math.max(
38+
memory[index1 - 1][index2],
39+
memory[index1][index2 - 1]
40+
);
41+
}
42+
}
43+
}
44+
45+
return memory[LENGTH1][LENGTH2];
46+
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* 알고달레 풀이 참고
3+
* @see https://www.algodale.com/problems/longest-repeating-character-replacement/
4+
*
5+
* TC: O(S)
6+
* right의 순회 + left의 순회
7+
* (곱이 아닌 더하기인 이유는 right 순회동안 left 순회의 최대 총합이 S이기 때문입니다.)
8+
*
9+
* SC: O(1)
10+
* 최악의 경우 26개의 소문자를 저장하는 memoryMap으로 인해 상수 복잡도를 갖게 됩니다.
11+
*
12+
* S: s.length
13+
*/
14+
15+
/**
16+
* @param {string} s
17+
* @param {number} k
18+
* @return {number}
19+
*/
20+
var characterReplacement = function (s, k) {
21+
// 1. 가장 긴 subString 길이
22+
let result = 0;
23+
24+
// 2. left, right 포인터 사이에서 등장한 문자 횟수를 기록한 Map과 최다 등장한 횟수를 기록한 변수
25+
const memory = new Map();
26+
let maxCount = 0;
27+
28+
let left = 0;
29+
let right = 0;
30+
31+
while (right < s.length) {
32+
// 3. '새로운 문자(s[right])의 갯수 기록'과 '최다 등장한 횟수 갱신'
33+
const newCount = (memory.has(s[right]) ? memory.get(s[right]) : 0) + 1;
34+
memory.set(s[right], newCount);
35+
maxCount = Math.max(maxCount, newCount);
36+
37+
// 4. k만큼 변경가능한 subString 길이를 맞추기 위해 left 이동
38+
while (right - left + 1 - maxCount > k) {
39+
const newCount = memory.get(s[left]) - 1;
40+
memory.set(s[left], newCount);
41+
left += 1;
42+
}
43+
44+
// 5. 가장 긴 subString 길이 갱신, right 이동
45+
result = Math.max(result, right - left + 1);
46+
right += 1;
47+
}
48+
49+
return result;
50+
};

merge-two-sorted-lists/wogha95.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* TC: O(List1 + List2)
3+
* List1, List2 전체 순회 1번씩 합니다.
4+
*
5+
* SC: O(1)
6+
* List1, List2의 길이와 무관한 고정된 데이터 공간을 사용합니다. (head, pointer 변수들)
7+
*
8+
* List1: list1.length, List2.length;
9+
*/
10+
11+
/**
12+
* Definition for singly-linked list.
13+
* function ListNode(val, next) {
14+
* this.val = (val===undefined ? 0 : val)
15+
* this.next = (next===undefined ? null : next)
16+
* }
17+
*/
18+
/**
19+
* @param {ListNode} list1
20+
* @param {ListNode} list2
21+
* @return {ListNode}
22+
*/
23+
var mergeTwoLists = function (list1, list2) {
24+
// 1. 둘 중 하나의 list가 없는 경우 반대편의 list를 반환
25+
if (!list1) {
26+
return list2;
27+
}
28+
if (!list2) {
29+
return list1;
30+
}
31+
32+
// 2. 정답을 반환할 시작점(head)와 list 순회시 필요한 pointer
33+
const head = new ListNode();
34+
let headPointer = head;
35+
let list1Pointer = list1;
36+
let list2Pointer = list2;
37+
38+
// 3. 두 list 모두 노드를 가진 경우
39+
while (list1Pointer && list2Pointer) {
40+
if (list1Pointer.val < list2Pointer.val) {
41+
list1Pointer = connectHeadAndListPointer(list1Pointer);
42+
} else {
43+
list2Pointer = connectHeadAndListPointer(list2Pointer);
44+
}
45+
}
46+
47+
// 4. 한쪽 list의 남은 노드 연결
48+
while (list1Pointer) {
49+
list1Pointer = connectHeadAndListPointer(list1Pointer);
50+
}
51+
52+
while (list2Pointer) {
53+
list2Pointer = connectHeadAndListPointer(list2Pointer);
54+
}
55+
56+
return head.next;
57+
58+
// 5. head의 list로 연결 후 다음 노드로 pointer 이동
59+
function connectHeadAndListPointer(listPointer) {
60+
headPointer.next = listPointer;
61+
listPointer = listPointer.next;
62+
headPointer = headPointer.next;
63+
64+
return listPointer;
65+
}
66+
};

sum-of-two-integers/wogha95.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* TC: O(Bit)
3+
* 올림 비트가 0일때까지 while을 실행하게된다.
4+
*
5+
* SC: O(log(max(a, b)))
6+
*
7+
* Bit: 2진수 a 와 b 중 비트 길이가 긴 것의 비트 길이
8+
*/
9+
10+
/**
11+
* @param {number} a
12+
* @param {number} b
13+
* @return {number}
14+
*/
15+
var getSum = function (a, b) {
16+
while (b !== 0) {
17+
const carry = (a & b) << 1;
18+
a = a ^ b;
19+
b = carry;
20+
}
21+
22+
return a;
23+
};

0 commit comments

Comments
 (0)