Skip to content

[uraflower] Week11 Solutions #1570

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
Jun 13, 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
33 changes: 33 additions & 0 deletions binary-tree-maximum-path-sum/uraflower.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
const maxPathSum = function (root) {
let max = root.val;

function getMaxSum(node) {
if (!node) return 0;

const leftVal = Math.max(getMaxSum(node.left), 0);
const rightVal = Math.max(getMaxSum(node.right), 0);

max = Math.max(node.val + leftVal + rightVal, max);

return node.val + Math.max(leftVal, rightVal);
}

getMaxSum(root);

return max;
};

// 시간복잡도: O(n)
// 공간복잡도: O(h) (h: 트리의 높이, 즉 재귀 스택 깊이)
39 changes: 39 additions & 0 deletions graph-valid-tree/uraflower.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @param {number} n
* @param {number[][]} edges
* @returns {boolean}
*/
function validTree(n, edges) {
// 트리의 조건을 만족하는지 확인(V = E + 1)
if (edges.length !== n - 1) {
return false;
}

const graph = Array.from({ length: n }).map(() => []);

for (const [u, v] of edges) {
graph[u].push(v);
graph[v].push(u);
}

const queue = [[-1, 0]]; // 부모 노드, 자식 노드
const visited = new Set();

while (queue.length) {
Copy link
Contributor

Choose a reason for hiding this comment

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

무방향 그래프가 트리의 조건인 connected && acyclic 을 만족하는지 확인하는 방법으로, BFS나 DFS 외에도 union-find도 있다고 해요!

저는 그래프나 트리 문제를 풀 때마다 너무 당연하게 BFS/DFS로만 푸는 경향이 있었는데, 이번 문제를 통해 union-find로도 풀어보게 되었어서 함께 공유드려요~!

const [parent, current] = queue.shift();
if (visited.has(current)) {
return false;
}
visited.add(current);

for (const neighbor of graph[current]) {
if (neighbor === parent) continue;
queue.push([current, neighbor]);
}
}

return visited.size === n;
}

// 시간복잡도: O(V + E)
// 공간복잡도: O(V)
27 changes: 27 additions & 0 deletions merge-intervals/uraflower.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @param {number[][]} intervals
* @return {number[][]}
*/
const merge = function (intervals) {
// 시작점 기준으로 정렬
intervals.sort((a, b) => Number(a[0]) - Number(b[0]));
const result = [];

for (const current of intervals) {
const last = result[result.length - 1];

// 겹치는 구간이 있으면, 구간의 끝점을 더 큰 것으로 덮어씌우기
if (last && current[0] <= last[1]) {
result[result.length - 1][1] = Math.max(current[1], last[1]);
}
// 겹치는 구간이 없으면, 새로 집어 넣기
else {
result.push(current);
}
}

return result;
};

// 시간복잡도: O(n * log n)
// 공간복잡도: O(n)
17 changes: 17 additions & 0 deletions missing-number/uraflower.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @param {number[]} nums
* @return {number}
*/
const missingNumber = function(nums) {
const n = nums.length;
let sum = (n * (n + 1)) / 2;

for (let num of nums) {
sum -= num;
}

return sum;
};

// 시간복잡도: O(n)
// 공간복잡도: O(1)
38 changes: 38 additions & 0 deletions reorder-list/uraflower.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {void} Do not return anything, modify head in-place instead.
*/
var reorderList = function (head) {
const nodes = {};
let current = head;
let n = 0; // 인덱스 역할

// 리스트를 순회하면서 각 노드를 객체에 저장
while (current) {
nodes[n] = current;
current = current.next;
nodes[n].next = null; // 여기서 모든 노드의 next를 null로 변경
// 이렇게 안 하면 next 바꾸기 한 다음에 맨 마지막 노드의 next만 null로 바꿔야 함
n++
}
Copy link
Contributor

Choose a reason for hiding this comment

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

추가적인 해시맵을 생성해 연결 리스트의 각 노드를 O(1)으로 조회할 수 있게 함으로써 가독성 좋게 쓰인 풀이인 것 같습니다!

다만, 속도가 다른 투 포인터를 이용하여 연결 리스트를 절반으로 나누고 오른쪽 리스트를 뒤집은 후, 두 리스트를 첫 노드부터 번갈아가며 다시 엮어나가는 방식으로 푼다면 추가 공간을 사용하지 않고 공간 복잡도를 O(1)으로 최적화 할 수 있을 것 같아요!


// 저장한 노드를 i, n-i, ... 순서로 접근하면서 next 바꾸기
for (let i = 0; i < Math.floor(n / 2); i++) {
nodes[i].next = nodes[n - i - 1];

// n-i-1 === i+1 인 경우, node.next = node 처럼 셀프 순환이 될 수 있음
if (n - i - 1 !== i + 1) {
nodes[n - i - 1].next = nodes[i + 1];
}
}
};

// 시간복잡도: O(n)
// 공간복잡도: O(n)