Skip to content

[sungjinwi] Week10 solution #1556

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
63 changes: 63 additions & 0 deletions course-schedule/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -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 <vector>
#include <queue>

using namespace std;

class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<vector<int>> graph(numCourses);
vector<int> inDgree(numCourses, 0);

for (auto& prerequisite : prerequisites) {
int crs = prerequisite[0];
int pre = prerequisite[1];
graph[pre].push_back(crs);
inDgree[crs]++;
}

queue<int> 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;
}
};
50 changes: 50 additions & 0 deletions invert-binary-tree/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -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) {}
};
32 changes: 32 additions & 0 deletions jump-game/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
풀이 :
마지막 인덱스를 시작점으로 하는 변수 lastReachable 선언
마지막 인덱스에 도달할 수 있는 가장 작은 인덱스를 저장
위에서 내려오면서 lastReachable 높이에 점프해서 닿을 수 있는 가장 작은 높이를 새로운 lastReachable로 업데이트
반복문이 끝나고 lastReachable == 0을 리턴한다

nums의 길이 : N

TC : O(N)
for문 반복 1회

SC : O(1)
변수 lastReachable 외에 추가적인 메모리 할당 없음
*/

#include <vector>
using namespace std;

class Solution {
public:
bool canJump(vector<int>& 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;
}
};
60 changes: 60 additions & 0 deletions merge-k-sorted-lists/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
풀이 :
최소힙을 사용해서 풀이한다
리스트의 각 맨앞 노드를 최소힙에 넣고 최소 값을 가진 노드를 dummy에 붙여나간 뒤 next를 다시 최소힙에 넣는 것을 반복

노드의 개수 : N, list의 개수 K

TC : O (N log K)
K개의 크기를 가지는 최소 힙에 넣고 제거하는 시간 -> logK * 모든 노드에 대한 순회 N

SC : O (K)
최소힙 크기는 K에 비례
*/

#include <vector>
#include <queue>

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<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, 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;
}
};
51 changes: 51 additions & 0 deletions search-in-rotated-sorted-array/sungjinwi.cpp
Original file line number Diff line number Diff line change
@@ -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 <vector>
using namespace std;

class Solution {
public:
int search(vector<int>& 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;
}
};