Skip to content

[sungjinwi] Week 11 solution #1578

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
59 changes: 59 additions & 0 deletions binary-tree-maximum-path-sum/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
풀이 :
result를 int의 최솟값으로 초기화하고 시작

두가지 기능을 하는 함수 하나를 생성
1. left, root->val, right의 합(하나의 path/\를 이룸)을 통해 maxSum을 업데이트
2. max (left 노드 합, right 노드 합)과 root를 더해서 return
-> left, right 둘 중 하나만 포함해야 상위 tree에서 path의 일부로 사용가능
/\
/ \
/ /
\
이 때, 음수 노드의 합은 max(0, value)를 통해 버리고 left + right + root->val을 통해 추가적인 계산 없이 maxSum 업데이트

노드 개수 : N

TC : O(N)
모든 노드 순회

SC : O(N)
재귀 호출 스택도 노드 개수에 비례
*/


#include <limits.h>
#include <algorithm>

using namespace std;

class Solution {
public:
int maxPathSum(TreeNode* root) {
int result = INT_MIN;

dfs(root, result);
return result;
}

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

int left = max(0, dfs(root->left, maxSum));
int right = max(0, dfs(root->right, maxSum));

maxSum = max(maxSum, left + right + root->val);

return root->val + max(left, right);
}
};

struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
62 changes: 62 additions & 0 deletions graph-valid-tree/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
풀이 :
graph가 tree가 되려면 모든 노드가 연결되어 있어야하고 순환이 없어야한다
간선이 노드 개수 n - 1보다 작으면 모든 노드 연결 불가능, 크면 무조건 순환이 생긴다
간선이 n - 1과 동일할 때 순환이 없으면 valid tree라고 판단 가능

Union-find 사용
- 시작할 때 각 노드는 자기 자신을 parent(root)로 가진다
- 노드가 서로 연결되있으면 한 union으로 합친 뒤 하나의 parent로 업데이트한다
- 이를 통해 한 parent를 가지는 한 그룹으로 묶이게 된다

find 함수는 한 그룹 전체의 parent를 재귀적으로 한 노드로 업데이트한다 (트리 깊이가 깊어져도 한번에 parent를 찾을 수 있게끔 경로최적화)

두 노드의 find()결과 값이 같으면 이미 한 그룹에 속하는 것이므로 이 두 노드에 간선을 잇는 것은 순환이 생기는 것이다
이를 통해 순환 있는지 판단

노드 개수 : V, 간선 개수 : E
E = V - 1일 때만 유의미한 연산하므로 E ≈ V

TC : O(V)
반복문 2회, find 함수의 재귀는 이론적으로 상수에 수렴한다고 한다

SC : O(V)
parent 배열
*/

#include <vector>
#include <unordered_map>

using namespace std;

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

parent.resize(n);
for (int i = 0; i < n; i++)
parent[i] = i;

for (auto& edge : edges) {
int a = edge[0], b = edge[1];
int rootA = find(a), rootB = find(b);
if (rootA == rootB)
return false;
parent[rootA] = rootB;
}
}

int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
}
};
38 changes: 38 additions & 0 deletions merge-intervals/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
풀이 :
시작시간으로 interval을 정렬한 뒤에 첫번째 interval을 ans에 넣는다(.back() 메서드의 에러 방지)
ans 배열의 마지막 interval과 시간이 겹치면 interval을 통합시키고
겹치지 않으면 ans에 현재 interval을 넣고 반복

interval 개수 : N

TC : O (N logN)
sort로 정렬

SC : O (1)
ans외에 추가적인 메모리 할당은 상수
*/

#include <vector>
#include <algorithm>
using namespace std;

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

sort(intervals.begin(), intervals.end());
ans.push_back(intervals[0]);

for (int i = 1; i < intervals.size(); i++) {
vector<int>& lastInterval = ans.back();

if (intervals[i][0] <= lastInterval[1])
lastInterval[1] = max(lastInterval[1], intervals[i][1]);
else
ans.push_back(intervals[i]);
}
return ans;
}
};
25 changes: 25 additions & 0 deletions missing-number/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
풀이 :
수식을 이용해 숫자가 빠지지 않았을경우 총합을 구하고 nums를 순회하면서 숫자들을 빼면 남은 숫자가 missing No.

nums의 길이 : N

TC : O(N)

SC : O(1)
*/

#include <vector>
using namespace std;

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

for (auto& num : nums)
sum -= num;
return sum;
}
};
50 changes: 50 additions & 0 deletions reorder-list/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
풀이 :
투포인터 기법을 이용해 중간 노드를 구해 리스트를 반으로 나누고 뒤의 그룹은 순서를 뒤집는다
번갈아가면서 다시 붙여준다

노드 총 개수 : N

TC : O(N)

SC : O(1)
*/

class Solution {
public:
void reorderList(ListNode* head) {
ListNode *slow = head, *fast = head;

while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}

ListNode *prev = nullptr, *curr = slow->next;
slow->next = nullptr;

while (curr) {
ListNode *tmp = curr->next;
curr->next = prev;
prev = curr;
curr = tmp;
}

ListNode *first = head, *second = prev;
while (second) {
ListNode *tmp1 = first->next, *tmp2 = second->next;
first->next = second;
second->next = tmp1;
first = tmp1;
second = tmp2;
}
}
};

struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};