diff --git a/course-schedule/sungjinwi.cpp b/course-schedule/sungjinwi.cpp new file mode 100644 index 000000000..52c9f7917 --- /dev/null +++ b/course-schedule/sungjinwi.cpp @@ -0,0 +1,63 @@ +/* + 풀이 : + BFS를 이용한 진입차수 기반 위상정렬 + + prerequisite에서 course로 방향 간선이 생기는 그래프 문제 + 그래프는 이중벡터로 만들고 선수과목 관계에 따라 초기화 (graph[선수과목]에 상위과목들을 담는다) + 과목을 들으려면 필요한 선수과목 수 -> inDgree에 배열로 저장 + + 선수과목이 필요없는 (inDgree에서 성분이 0인) 과목 먼저 큐에 넣는다 + 과목을 수강하면 finished++로 수강완료 표시, 해당 과목을 선수과목으로 가지는 과목들에서 진입차수를 1씩 뺸다 + 진입차수가 0이 되는 과목을 큐에 넣어서 반복 + + 큐가 완전히 빌 떄까지 반복했을 떄 모든 과목을 이수 가능하면(finished == numCourses) true 아니면 false + + 수강과목 수 : V(Vertex), 선수과목 관계 수 : E(Edge) + + TC : O (V + E) + prerequisites(E)과 numCourses(V)만큼에 대해 각각 반복문 + + SC : O (V + E) + 기본적으로 V만큼의 빈 벡터를 가지고 있고 추가적으로 E만큼 성분이 push된다 +*/ + +#include +#include + +using namespace std; + +class Solution { + public: + bool canFinish(int numCourses, vector>& prerequisites) { + vector> graph(numCourses); + vector inDgree(numCourses, 0); + + for (auto& prerequisite : prerequisites) { + int crs = prerequisite[0]; + int pre = prerequisite[1]; + graph[pre].push_back(crs); + inDgree[crs]++; + } + + queue q; + int finished = 0; + + for (int i = 0; i < numCourses; i++) { + if (inDgree[i] == 0) + q.push(i); + } + + while (!q.empty()) { + int cur = q.front(); + q.pop(); + + for (auto& next : graph[cur]) { + if (--inDgree[next] == 0) + q.push(next); + } + finished++; + } + + return finished == numCourses; + } + }; diff --git a/invert-binary-tree/sungjinwi.cpp b/invert-binary-tree/sungjinwi.cpp new file mode 100644 index 000000000..690e0f57d --- /dev/null +++ b/invert-binary-tree/sungjinwi.cpp @@ -0,0 +1,50 @@ +/* + 풀이 : + left와 right을 스왑하는 과정을 dfs를 이용해서 끝까지 반복한다 + + 트리의 깊이 : N + + TC : O(2^N) + 깊이마다 2번씩 재귀함수 호출 + + SC : O(2^N) + 깊이마다 2번씩 재귀함수 호출로 인한 스택 쌓임 +*/ + +/** + * Definition for a binary tree node. + * 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) {} + * }; + */ +class Solution { + public: + TreeNode* invertTree(TreeNode* root) { + if (!root) + return nullptr; + + TreeNode* tmp = root->left; + + root->left = root->right; + root->right = tmp; + + invertTree(root->left); + invertTree(root->right); + + return root; + } + }; + +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/jump-game/sungjinwi.cpp b/jump-game/sungjinwi.cpp new file mode 100644 index 000000000..654793e09 --- /dev/null +++ b/jump-game/sungjinwi.cpp @@ -0,0 +1,32 @@ +/* + 풀이 : + 마지막 인덱스를 시작점으로 하는 변수 lastReachable 선언 + 마지막 인덱스에 도달할 수 있는 가장 작은 인덱스를 저장 + 위에서 내려오면서 lastReachable 높이에 점프해서 닿을 수 있는 가장 작은 높이를 새로운 lastReachable로 업데이트 + 반복문이 끝나고 lastReachable == 0을 리턴한다 + + nums의 길이 : N + + TC : O(N) + for문 반복 1회 + + SC : O(1) + 변수 lastReachable 외에 추가적인 메모리 할당 없음 +*/ + +#include +using namespace std; + +class Solution { + public: + bool canJump(vector& nums) { + int lastReachable = nums.size() - 1; + + for (int i = nums.size() - 2; i >= 0; i--) { + if (i + nums[i] >= lastReachable) + lastReachable = i; + } + + return lastReachable == 0; + } + }; diff --git a/merge-k-sorted-lists/sungjinwi.cpp b/merge-k-sorted-lists/sungjinwi.cpp new file mode 100644 index 000000000..bb660d859 --- /dev/null +++ b/merge-k-sorted-lists/sungjinwi.cpp @@ -0,0 +1,60 @@ +/* + 풀이 : + 최소힙을 사용해서 풀이한다 + 리스트의 각 맨앞 노드를 최소힙에 넣고 최소 값을 가진 노드를 dummy에 붙여나간 뒤 next를 다시 최소힙에 넣는 것을 반복 + + 노드의 개수 : N, list의 개수 K + + TC : O (N log K) + K개의 크기를 가지는 최소 힙에 넣고 제거하는 시간 -> logK * 모든 노드에 대한 순회 N + + SC : O (K) + 최소힙 크기는 K에 비례 +*/ + +#include +#include + +using namespace std; + +/** + * Definition for singly-linked list. + * 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) {} + * }; + */ + +struct cmp { + bool operator()(const ListNode* a, const ListNode* b) { + return a->val > b->val; + } +}; + +class Solution { +public: + ListNode* mergeKLists(vector& lists) { + priority_queue, cmp> pq; + + for (auto list : lists) { + if (list) + pq.push(list); + } + + ListNode dummy, *tail = &dummy; + + while (!pq.empty()) { + ListNode* minNode = pq.top(); pq.pop(); + + if (minNode->next) + pq.push(minNode->next); + + tail->next = minNode; + tail = minNode; + } + return dummy.next; + } +}; diff --git a/search-in-rotated-sorted-array/sungjinwi.cpp b/search-in-rotated-sorted-array/sungjinwi.cpp new file mode 100644 index 000000000..68aa3d4e0 --- /dev/null +++ b/search-in-rotated-sorted-array/sungjinwi.cpp @@ -0,0 +1,51 @@ +/* + 풀이 : + mid를 기준으로 왼쪽이 정렬된 경우, 오른쪽이 정렬된 경우를 나누고 + 정렬된 숫자 범위에 target값이 존재하느냐에 따라 범위를 이분 탐색으로 좁혀나간다 + + - 이분탐색 시 종료조건 및 비교조건에서 등호를 포함시킬지 여부 고려 필요 + while (left <= right) -> 탐색 범위에 양 끝 인덱스 포함 + -> left = mid + 1 또는 right = mid - 1 로 새로운 범위 업데이트 + + while (left < right) -> 탐색 범위에 오른쪽 끝 인덱스는 제외 + -> left = mid + 1 또는 right = mid 로 새로운 범위 업데이트 + + nums 개수 N + + TC : O(logN) + 이분 탐색으로 찾아서 log2N의 복잡도를 갖는다 + + SC : O(1) +*/ + +#include +using namespace std; + +class Solution { + public: + int search(vector& nums, int target) { + int left = 0, right = nums.size() - 1; + + while (left <= right) + { + int mid = left + (right - left) / 2; + + if (nums[mid] == target) + return mid; + + if (nums[left] <= nums[mid]) { + if (nums[left] <= target && target < nums[mid]) + right = mid -1; + else + left = mid + 1; + } + else { + if (nums[mid] < target && target <= nums[right]) + left = mid + 1; + else + right = mid - 1; + } + } + return -1; + } + };