Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
73 changes: 73 additions & 0 deletions longest-repeating-character-replacement/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* 풀이
* - 주어진 s로 만들 수 있는 가장 긴 valid substring의 길이를 찾는 문제입니다
* - valid substring: 최대 k개의 문자를 바꿔서, 모든 문자가 같게 만들 수 있는 substring
*
* - 두 단계로 나누어 풀이에 대해 생각할 수 있습니다
*
* - 1. 특정 길이의 valid substring을 만들 수 있는지 확인
* - 함수 bool can_make_valid_substring(string const s, int substr_length, int k)
* - 특정 길이의 substring에 대해서, 등장 빈도가 가장 높은 문자의 빈도수를 저장합니다 (max_freq)
* 만약 해당 substring이 valid substring이라면, max_freq + k >= substr_length 이어야 합니다
*
* - 2. 최대 길이의 valid substring을 찾는다
* - 이진탐색을 통해 최대 길이를 찾는다
* - 함수 int characterReplacement(string s, int k)
* - 주어진 문자열 s로 만들 수 있는 substring의 길이는 1이상 s.size() 이하입니다
* 이진 탐색의 범위를 위에서 언급한 대로 설정하고, 현재 탐색하려는 길이 (mid)에 대해서
* can_make_valid_substring 함수를 호출하여 현재 길이로 valid substring을 만들 수 있는지 확인합니다
* 이진 탐색 알고리즘의 전개 및 결과에 대한 설명은 https://github.com/DaleStudy/leetcode-study/discussions/332를 참고해주세요 :)
*
* Big O
* - N: 주어진 문자열 s의 길이
* - K: 주어진 정수 k
*
* - Time complexity: O(N * logN)
* - Space complexity: O(1)
*/

class Solution {
public:
bool can_make_valid_substring(string const s, int substr_length, int k) {
// 문자의 빈도수를 저장하는 배열입니다
array<int, 26> freq;
freq.fill(0);

// 최대 빈도수를 저장하는 변수입니다
int max_freq = 0;

int window_start = 0;

for (int window_end = 0; window_end < s.size(); ++window_end) {
++freq[s[window_end] - 'A'];

int curr_size = window_end - window_start + 1;
if (curr_size > substr_length) {
--freq[s[window_start] - 'A'];
++window_start;
}

max_freq = max(max_freq, freq[s[window_end] - 'A']);
if (max_freq + k >= substr_length) return true;
}

return false;
}

int characterReplacement(string s, int k) {
int lo = 1;
int hi = s.size() + 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;

if (can_make_valid_substring(s, mid, k)) lo = mid + 1;
Copy link
Member

Choose a reason for hiding this comment

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

바이너리 서치로 푸시다니 엄청 신선하네요
end 포인터를 한 칸씩 옮기면서 start 포인터를 움직이는 방식으로 풀었는데, 여기서는 "만들 수 있는 부분 문자열의 길이를 lo로 갱신" 하는 것이 핵심인가 보네요 ㅎㅎ 잘 봤습니다

Copy link
Contributor Author

Choose a reason for hiding this comment

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

저도 아이디어가 안 떠올라서 리트코드의 에디토리얼을 참고했는데, 신선하더라구요 ㅎㅎ 감사합니다
이 풀이보다 시간복잡도 면에서 더 효율적인 풀이가 있긴 하지만요

else hi = mid;
}

// 이진탐색이 종료되면 lo는 최대 길이보다 1 큰 값이 된다.
// EX: hi lo
// T T T T F F F F
// 따라서 최대 길이는 lo - 1이 된다
return lo - 1;
}
};
57 changes: 57 additions & 0 deletions merge-two-sorted-lists/flynn.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* 풀이
* - 주어진 두 링크드리스트의 각 node를 비교하며 반환할 새 링크드리스트에 추가해줍니다
*
* Big O
* - N: 주어진 두 링크드리스트 list1, list2의 노드 개수의 총합
*
* - Time complexity: O(N)
* - Space complexity: O(1)
* - 반환하는 링크드리스트를 복잡도에 포함시키지 않을 시, 공간복잡도는 N에 상관 없이 일정합니다
*/

/**
* 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* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* head = new ListNode();
ListNode* node = head;

ListNode* p = list1;
ListNode* q = list2;

while (p != nullptr && q != nullptr) {
if (p->val < q->val) {
node->next = p;
p = p->next;
} else {
node->next = q;
q = q->next;
}
node = node->next;
}

while (p != nullptr) {
node->next = p;
p = p->next;
node = node->next;
}

while (q != nullptr) {
node->next = q;
q = q->next;
node = node->next;
}
Copy link
Member

@jdalma jdalma Oct 4, 2024

Choose a reason for hiding this comment

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

제가 C++을 잘 모르지만.. 혹시 while문을 쓰지 않고 아래처럼 참조를 바로 담아주는 것은 어떨까요??

  if (l1 != null) node.next = l1
  if (l2 != null) node.next = l2

Copy link
Contributor Author

Choose a reason for hiding this comment

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

앗 그렇네요 ㅎㅎㅎ 좋은 지적 감사합니다 반영하겠습니다!


return head->next;
}
};