Skip to content
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

[Flynn] Week7 #486

Merged
merged 7 commits into from
Sep 26, 2024
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
42 changes: 42 additions & 0 deletions longest-substring-without-repeating-characters/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* 풀이
* - 주어진 문자열 `s`를 한 번 조회합니다
* - lookup이라는 해시맵 객체를 이용하여 현재 조회하고 있는
* substring에 반복되는 문자가 있는지 검사합니다
*
* Big O
* - N: 주어진 문자열 `s`의 길이
*
* - Time complexity: O(N)
* - Space complexity: O(N)
*/

class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.size() == 0) return 0;

unordered_map<char, int> lookup;
lookup.insert({s[0], 0});

int res = 1;

int start = 0;
int end = 1;

while (end < s.size()) {
if (lookup.find(s[end]) != lookup.end()
&& lookup[s[end]] >= start) {
start = lookup[s[end]] + 1;
}

lookup[s[end]] = end;

res = max(res, end - start + 1);

++end;
}

return res;
}
};
59 changes: 59 additions & 0 deletions number-of-islands/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* 풀이
* - bfs를 활용합니다
*
* Big O
* - M: grid의 행의 수
* - N: grid의 열의 수
*
* - Time complexity: O(MN)
* - 각 좌표는 최대 한 번씩만 조회하게 됩니다
* - Space complexity: O(MN)
* - 방문 여부를 기록하기 위해 visit 배열이 사용됩니다
* - queue에 쌓이는 원소의 개수는 최대 MN개까지 증가할 수 있습니다
*/

class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int m = grid.size();
int n = grid[0].size();

vector<vector<bool>> visit;
for (int r = 0; r < m; ++r) {
vector<bool> row;
for (int c = 0; c < n; ++c) {
row.push_back(false);
}
visit.push_back(row);
}

pair<int, int> dirs[4] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

int res = 0;
queue<pair<int, int>> q;
for (int r = 0; r < m; ++r) {
for (int c = 0; c < n; ++c) {
if (visit[r][c] == false && grid[r][c] == '1') {
++res;
q.push({r, c});
while (!q.empty()) {
auto p = q.front();
q.pop();
for (auto dir : dirs) {
pair<int, int> next = {p.first + dir.first, p.second + dir.second};
if (0 <= next.first && next.first < m && 0 <= next.second && next.second < n) {
if (visit[next.first][next.second] == false && grid[next.first][next.second] == '1') {
q.push(next);
visit[next.first][next.second] = true;
Comment on lines +45 to +48
Copy link
Contributor

Choose a reason for hiding this comment

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

if문이 해당 조건에 충족시 depth가 들어가게 되는데, 조건에 불충분시 for문을 continue 하는 방법으로 하면 어떨까요?
저는 first, second가 범위 밖에 있으면 바로 continue해서 다음으로 넘어가는 방식을 사용해서 depth를 줄이고 가독성이 높아진다고 생각해서요 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

좋은 의견 감사합니닷!
요거는 살짝 스타일의 차이인 것 같아서 그대로 두겠습니다
저는 특정 조건일 때 연산하기특정 조건일 때는 연산 안 하고 넘기기보다 더 좋아서 저런 식으로 하고 있습니다
depth는 스타일에 따라 더 읽기 까다로울 수도 있겠네요 ㅎㅎ ㅜ

}
}
}
}
}
}
}

return res;
}
};
54 changes: 54 additions & 0 deletions reverse-linked-list/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* 풀이
* - 생략, 주석 참고
*
* Big O
* - N: 주어진 링크드 리스트 `head`의 길이
*
* - Time complexity: O(N)
* - Space complexity: O(1)
*/

/**
* 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) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == nullptr) return head;
// example: a - b - c - d

ListNode* root = new ListNode();
root->next = head;
// root - a - b - c - d

ListNode* p = head;
Copy link
Contributor

Choose a reason for hiding this comment

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

p 사용 대신 head 자체를 사용해서 풀 수 있을지 궁금합니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

네 토니님 말씀대로 p를 선언하는 대신 head를 그대로 이용할 수 있습니다
p를 굳이 새로 선언해서 사용하는 이유는 q 변수의 변수명이 적절한 것이 생각나지 않아서..
head -> p로 새로 선언하고 그 다음 변수에 q라고 이름을 붙여주었습니다 ㅎㅎㅎ

ListNode* q = p->next;
// root - a - b - c - d
// (p) (q)

while (q != nullptr) {
p->next = q->next;
// root - a - c - d
// b /
q->next = root->next;
// root - a - c - d
// b /
root->next = q;
// root - b - a - c - d
// (q) (p)
q = p->next;
// root - b - a - c - d
// (p) (q)
}

return root->next;
}
};
60 changes: 60 additions & 0 deletions set-matrix-zeroes/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* 풀이
* - matrix 전체를 탐색하다가 값이 0인 좌표를 찾으면
* 그 좌표의 첫번째 열, 첫번째 행 좌표에 표시를 합니다
* if matrix[r][c] == 0
* matrix[r][0] = 0
* matrix[0][c] = 0
* - 만약 해당 좌표가 첫번째 행이거나 첫번째 열이라면 따로 기록해둡니다
* - 첫번째 완전탐색을 마친 후엔 matrix의 첫번째 행, 열을 보고 문제에서 요구하는 바를 수행합니다
*
* Big O
* - M: matrix의 행 개수
* - N: matrix의 열 개수
*
* - Time complexity: O(MN)
* - Space complexity: O(1)
*
*/

class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();

bool first_row = false;
bool first_col = false;

for (int r = 0; r < m; ++r) {
for (int c = 0; c < n; ++c) {
if (!matrix[r][c]) {
if (!r) first_row = true;
if (!c) first_col = true;
matrix[r][0] = 0;
matrix[0][c] = 0;
Comment on lines +34 to +35
Copy link
Contributor

Choose a reason for hiding this comment

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

기존 배열을 사용해서 기록하면 O(1)도 가능하군요! 한 수 배웠습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

저도 처음엔 O(MN), O(M + N) 공간복잡도 풀이를 했다가 더 나은 방법은 없을까 다른 사람들 솔루션을 구경하다가 배워 온 것 입니다 헤헤

}
}
}

for (int r = 1; r < m; ++r) {
if (!matrix[r][0]) {
for (int c = 1; c < n; ++c) matrix[r][c] = 0;
}
}

for (int c = 1; c < n; ++c) {
if (!matrix[0][c]) {
for (int r = 1; r < m; ++r) matrix[r][c] = 0;
}
}
Comment on lines +40 to +50
Copy link
Contributor

Choose a reason for hiding this comment

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

위에서 이미 double for loop이 사용되었기 때문에, 이 부분도 이중 포문으로 처리 하셔도 될 것 같아요! 근데 나눠두는게 이해하기 더 직관적이고 이해하기 편한것 같이 보이네요!

Copy link
Contributor Author

@obzva obzva Sep 26, 2024

Choose a reason for hiding this comment

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

제가 잘 이해를 못했는데, double loop 예시 코드와 그렇게 바꿨을 때의 이점을 설명 부탁드려도 될까요? :)


if (first_row) {
for (int c = 0; c < n; ++c) matrix[0][c] = 0;
}

if (first_col) {
for (int r = 0; r < m; ++r) matrix[r][0] = 0;
}
}
};
31 changes: 31 additions & 0 deletions unique-paths/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* 풀이
* - 조합 공식을 사용하면 overflow 및 시간초과를 일으킬 수 있습니다
* - 모든 좌표에 대해 uniquePaths를 계산하는 방식을 사용합니다
* - 특정 좌표의 uniquePaths를 계산하기 위해서는 두 행만 필요하기 때문에 길이 m의 배열 두 개를 이용합니다
*
* Big O
* - Time complexity: O(MN)
* - Space compexity: O(N)
*/

class Solution {
public:
int uniquePaths(int m, int n) {
vector<int> row1;
vector<int> row2;

for (int i = 0; i < n; ++i) row1.push_back(1);
row2.push_back(1);
for (int i = 1; i < n; ++i) row2.push_back(0);

for (int j = 1; j < m; ++j) {
for (int i = 1; i < n; ++i) row2[i] = row1[i] + row2[i - 1];
swap(row1, row2);
row2[0] = 1;
for (int i = 1; i < n; ++i) row2[i] = 0;
}

return row1[n - 1];
}
};