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] week4 #429

Merged
merged 5 commits into from
Sep 7, 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
37 changes: 37 additions & 0 deletions longest-consecutive-sequence/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* 풀이
* - 주어진 배열 `nums`로 set `s`를 만듭니다
* - `nums`를 조회하는데, 현재 조회 중인 `num`에 대하여 `num - 1`이 `s`에 포함되지 않는 경우만 while문을 실행하여 subsequence의 길이를 측정합니다
* - `num - 1`이 `s`에 포함되지 않는다는 것은 `num`이 해당 subsequence의 첫 수임을 뜻합니다
*
* Big-O
* - N: 주어진 배열 `nums`의 길이
*
* - Time complexity: O(N)
* - 이중 반복문의 구조를 가졌지만, 조건문때문에 각 원소를 한 번씩만 조회합니다
*
* - Space complexity: O(N)
* - `nums`를 구성하는 원소가 모두 고유한 정수일 경우, `s`의 크기가 `nums`만큼 커질 수 있습니다
*/

class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> s(nums.begin(), nums.end());

int res = 0;
for (int num : nums) {
if (s.find(num - 1) != s.end()) continue;

int curr = num;
int streak = 1;
while (s.find(curr + 1) != s.end()) {
++curr;
++streak;
}
res = max(res, streak);
}

return res;
}
};
32 changes: 32 additions & 0 deletions maximum-product-subarray/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* 풀이
* - 주어진 배열 `nums`를 순서대로 조회합니다
* - 0과 음수를 곱하는 경우를 고려하기 위해 현재 subarray의 곱의 최대값뿐만 아니라 최소값 또한 기록합니다
*
* Big-O
* - N: 주어진 배열 `nums`의 size
*
* - Time complexity: O(N)
* - Space complexity: O(1)
*/

class Solution {
public:
int maxProduct(vector<int>& nums) {
int max_prod = nums[0];
int min_prod = nums[0];
int res = nums[0];

for (int i = 1; i < nums.size(); i++) {
int curr = nums[i];

int tmp_max = max(curr, max(curr * max_prod, curr * min_prod));
min_prod = min(curr, min(curr * max_prod, curr * min_prod));
max_prod = tmp_max;

res = max(res, max_prod);
}

return res;
}
};
38 changes: 38 additions & 0 deletions missing-number/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* 풀이
* - 특정 정수가 `nums` 배열을 통해 주어졌는지 여부를 체크하는 배열 `check`를 만듭니다
* - `nums`를 조회하며 `check`배열의 값들을 변경합니다
* - `check`배열을 조회하여 누락되었던 정수를 확인합니다
*
* Big-O
* - N: 주어진 배열 `nums`의 크기
*
* - Time Complexity: O(N)
* - 배열 `nums`를 조회하는 반복문은 O(N)의 시간 복잡도를 가집니다
* - 배열 `check`를 조회하는 반복문 또한 O(N)의 시간 복잡도를 가집니다
* - 따라서 전체 시간 복잡도는 O(N)입니다
*
* - Space Complexity: O(N)
* - `check`배열의 크기가 입력값에 비례하여 선형적으로 증가합니다
*/

class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();

vector<bool> check(n + 1, false);

for (auto num : nums) check[num] = true;

int res;
for (int i = 0; i < n + 1; i++) {
if (!check[i]) {
res = i;
break;
}
}

return res;
}
};
36 changes: 36 additions & 0 deletions valid-palindrome/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* 풀이
* - 주어진 string `s`의 양 끝에서부터 차례대로 비교해가며 palindrome 여부를 판단합니다
*
* Big-O
* - N: 주어진 string `s`의 길이
*
* - Time Complexity: O(N)
* - `s`가 palindrome인 경우, `s` 전체를 탐색하므로 O(N)의 시간복잡도를 가집니다
*
* - Space Complexity: O(1)
* - 입력값과 무관하게 일정한 저장공간을 사용합니다
*/

class Solution {
public:
bool isPalindrome(string s) {
string::iterator lo = s.begin();
string::iterator hi = s.end();

while (lo <= hi) {
if (isalnum(*lo) && isalnum(*hi)) {
if (tolower(*lo) != tolower(*hi)) return false;
else {
++lo;
--hi;
continue;
}
}
if (!isalnum(*lo)) ++lo;
if (!isalnum(*hi)) --hi;
}

return true;
}
};
72 changes: 72 additions & 0 deletions word-search/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* 풀이
* - dfs와 backtracking을 이용하여 풀었습니다
*
* Big-O
* - M: 주어진 grid `board`의 행 수
* - N: 주어진 grid `board`의 열 수
* - W: 주어진 string `word`의 size
*
* - Time complexity: O(M * N * 3 ^ W)
* - `exist`함수가 grid 원소 모두를 조회합니다 -> O(M * N)
* - 만약 `dfs`함수가 실행될 경우, 해당 함수는 최대 3방향에 대해 재귀호출을 실행합니다 (이전 좌표로는 `dfs`를 호출하지 않기 때문)
Copy link
Contributor

Choose a reason for hiding this comment

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

dfs가 종료조건에 의해 조기 종료 되더라도 호출 자체는 4방향으로 생각하는것이 맞지 않을까요?
특히 최초 요청의 경우에는 조기종료 없이 4방향으로 호출이 진행될텐데, 이부분을 3방향으로만 생각해도 될까 싶어서 의견드립니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

네 그럼 4 * 3^W 의 형태가 될텐데요, W의 크기가 증가함에 따라 3배씩 증가하니까 Big-O를 산정하는 관점에서는 O(3^W)로 보는 것이 맞다고 생각했습니다
이 부분은 저도 좀 더 준비해서 다음 시간에 발표해보겠습니다

Copy link
Contributor Author

Choose a reason for hiding this comment

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

만약 4방향으로 호출하더라도 1방향은 이미 방문했던 방향이기에 유의미한 연산을 진행하지 않는다고 생각했습니다
그래서 Big-O를 따질 땐 빠져야 한다고 생각했어요

* - 재귀 호출 스택의 크기는 주어진 string `word`의 길이에 비례합니다 -> O(3^W)
*
* - Space complexity: O(M * N + W)
* - 재귀 호출 스택의 크기는 주어진 string `word`의 길이에 비례합니다 -> O(W)
* - 탐색 여부를 기록하는 `visit` 배열의 크기는 `board`와 같습니다 -> O(M * N)
*/

class Solution {
public:
bool dfs(vector<vector<char>>& board, string word, vector<vector<bool>>& visit, int idx, int r, int c) {
if (word.size() - 1 == idx) return true;

pair<int, int> dirs[4] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int R = board.size();
int C = board[0].size();

visit[r][c] = true;

int next_idx = idx + 1;

bool res = false;

for (auto dir : dirs) {
int next_r = r + dir.first;
int next_c = c + dir.second;

if (0 <= next_r && next_r < R && 0 <= next_c && next_c < C && !visit[next_r][next_c]) {
if (board[next_r][next_c] == word[next_idx] && dfs(board, word, visit, next_idx, next_r, next_c)) {
res = true;
break;
}
}
}

visit[r][c] = false;

return res;
}

bool exist(vector<vector<char>>& board, string word) {
int R = board.size();
int C = board[0].size();
vector<vector<bool>> visit;
for (int i = 0; i < R; i++) {
vector<bool> tmp;
for (int j = 0; j < C; j++) {
tmp.push_back(false);
}
visit.push_back(tmp);
}

for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (board[i][j] == word[0] && dfs(board, word, visit, 0, i, j)) return true;
}
}

return false;
}
};