Skip to content

[crumbs22] Week 11 Solutions #1577

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 2 commits into from
Jun 15, 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
27 changes: 27 additions & 0 deletions binary-tree-maximum-path-sum/crumbs22.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Solution {
public:
int maxPathSum(TreeNode* root) {
int res = INT_MIN;

dfs(root, res);
return res;
}

int dfs(TreeNode* root, int& res) {
if (!root)
return 0;

// 좌측 부분트리, 우측 부분트리를 각각 계산할 때 dfs의 '반환값'을 활용
// 음수값이 나올 경우는 0으로 대체함
int left = max(0, dfs(root->left, res));
int right = max(0, dfs(root->right, res));

// 최종 반환할 값 업데이트
// 좌측 트리, 우측 트리, 루트 노드를 모두 통과하는 경로가 현재까지 최댓값인지 비교해서 갱신
res = max(res, root->val + left + right);

// 상위 노드로 전달되는 값은 root의 값을 포함하는 경로의 값이다
// 따라서 좌측 트리 혹은 우측 트리 중 하나의 경로만을 선택해서 통과할 수 있다
return root->val + max(left, right);
}
};
57 changes: 57 additions & 0 deletions graph-valid-tree/crumbs22.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
valid tree 조건
1. 사이클이 없어야한다
2. 모든 각 노드들은 적어도 하나의 다른 노드와 연결되어 있어야 한다

인접 리스트 형식으로 무방향 간선 정보를 저장하고,
dfs 재귀 탐색으로 방문 체크 후 자식 노드를 재귀적으로 방문하면서 사이클 판단
*/

class Solution {
public:
/**
* @param n: An integer
* @param edges: a list of undirected edges
* @return: true if it's a valid tree, or false
*/
bool validTree(int n, vector<vector<int>> &edges) {
if (edges.size() != n - 1)
return false;

// 인접한 노드들을 요소로 가지는 adj 배열 생성
vector<vector<int>> adj(n);

for (auto edge : edges) {
int u = edge[0];
int v = edge[1];
adj[u].push_back(v);
adj[v].push_back(u);
}

// 방문 기록
vector<bool> visited(n, false);
if (!dfs(0, -1, adj, visited))
return false;

// 모든 노드가 방문되었는지 (연결되는지) 확인
for (bool v : visited) {
if (!v)
return false;
}
return true;
}

bool dfs(int node, int parent, vector<vector<int>>& adj, vector<bool> visited) {
visited[node] = true;

for (int neighbor : adj[node]) {
if (neighbor == parent)
continue ; // 바로 이전 노드는 무시(왕복 방지)
if (visited[neighbor])
return false; // 사이클 탐지
if (!dfs(neighbor, node, adj, visited))
return false;
}
return true;
}
};
31 changes: 31 additions & 0 deletions merge-intervals/crumbs22.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
이전 interval의 끝점과 현재 interval의 시작점을 비교해서 구간 겹침을 판단
구간이 겹친다면 prev를 갱신
구간이 겹치지 않을 때 반환 벡터 res에 prev 추가하고 기준점 갱신
intervals를 한 번 반복하므로 시간복잡도 O(n)과 처음 정렬에 O(nlogn) 소요되므로
최종 시간 복잡도는 O(nlogn)
추가적으로 사용하는 공간은 반환배열밖에 없으므로 O(1)의 공간복잡도 가짐
*/

class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> res;

sort(intervals.begin(), intervals.end());

vector<int> prev = intervals[0];
for (auto i : intervals) {
if (i[0] <= prev[1]) {
prev[0] = min(prev[0], i[0]);
Copy link
Contributor

Choose a reason for hiding this comment

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

맨처음에 sort를 해주셔서 배열 첫번째 요소는 비교 안해도 괜찮을 거 같습니다!

prev[1] = max(prev[1], i[1]);
} else {
res.push_back(prev); // 이전 병합 구간 저장
prev = i; // 새로운 기준 시작
}
}
res.push_back(prev);

return res;
}
};
18 changes: 18 additions & 0 deletions missing-number/crumbs22.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
풀이방법: 0부터 n까지의 합은 n*(n + 1)/2 이라는 수학적 사실을 활용,
nums 배열을 한 번만 순회하므로 시간복잡도는 O(n)
추가적으로 사용하는 공간 없으므로 공간복잡도는 O(1)이다.
*/

class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();
int res = n * (n + 1) / 2;

for (int num : nums) {
res -= num;
}
return (res);
}
};
38 changes: 38 additions & 0 deletions reorder-list/crumbs22.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
큐와 스택구조를 활용해 노드의 주소를 각각 저장해놓고
큐에서 한 번, 스택에서 한 번 요소를 빼와서 재정렬한다
링크드리스트를 한 번 순회하면서 push하고 같은 길이만큼 한 번 더 순회하므로 O(2n)의 시간복잡도와
노드 길이만큼의 자료구조를 2개 더 사용하므로 O(2n)의 공간복잡도를 사용
*/

class Solution {
public:
void reorderList(ListNode* head) {
ListNode* tmp = head;
queue<ListNode*> q;
stack<ListNode*> s;

while (tmp) {
s.push(tmp);
q.push(tmp);
tmp = tmp->next;
}

// 큐 - 스택 - 큐 - 스택 ...
// 큐는 앞에서 1/2을, 스택은 뒤에서 1/2을 반복하며 요소 추출
int len = q.size();
tmp = q.front();
q.pop();

for (int i = 0; i < len / 2; i++) {
tmp->next = s.top();
s.pop();
tmp = tmp->next;
tmp->next = q.front();
q.pop();
tmp = tmp->next;
}
tmp->next = nullptr;

}
};