diff --git a/binary-tree-maximum-path-sum/sungjinwi.cpp b/binary-tree-maximum-path-sum/sungjinwi.cpp new file mode 100644 index 000000000..af5adde44 --- /dev/null +++ b/binary-tree-maximum-path-sum/sungjinwi.cpp @@ -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 +#include + +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) {} +}; diff --git a/graph-valid-tree/sungjinwi.cpp b/graph-valid-tree/sungjinwi.cpp new file mode 100644 index 000000000..25b2c71f7 --- /dev/null +++ b/graph-valid-tree/sungjinwi.cpp @@ -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 +#include + +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 parent; + bool validTree(int n, vector> &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]; + } +}; diff --git a/merge-intervals/sungjinwi.cpp b/merge-intervals/sungjinwi.cpp new file mode 100644 index 000000000..f0d736e27 --- /dev/null +++ b/merge-intervals/sungjinwi.cpp @@ -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 +#include +using namespace std; + +class Solution { + public: + vector> merge(vector>& intervals) { + vector> ans; + + sort(intervals.begin(), intervals.end()); + ans.push_back(intervals[0]); + + for (int i = 1; i < intervals.size(); i++) { + vector& 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; + } + }; diff --git a/missing-number/sungjinwi.cpp b/missing-number/sungjinwi.cpp new file mode 100644 index 000000000..a5e8bcb61 --- /dev/null +++ b/missing-number/sungjinwi.cpp @@ -0,0 +1,25 @@ +/* + 풀이 : + 수식을 이용해 숫자가 빠지지 않았을경우 총합을 구하고 nums를 순회하면서 숫자들을 빼면 남은 숫자가 missing No. + + nums의 길이 : N + + TC : O(N) + + SC : O(1) +*/ + +#include +using namespace std; + +class Solution { + public: + int missingNumber(vector& nums) { + int n = nums.size(); + int sum = n * (n + 1) / 2; + + for (auto& num : nums) + sum -= num; + return sum; + } + }; diff --git a/reorder-list/sungjinwi.cpp b/reorder-list/sungjinwi.cpp new file mode 100644 index 000000000..52e8d726c --- /dev/null +++ b/reorder-list/sungjinwi.cpp @@ -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) {} +};