From 031aa65ec2efc3f06762fe6845250980086657e9 Mon Sep 17 00:00:00 2001 From: not-phoenix-w Date: Fri, 30 May 2025 19:50:09 +0300 Subject: [PATCH 01/10] hw --- task_01/src/main.cpp | 23 +++++- task_02/src/main.cpp | 3 + task_03/src/main.cpp | 20 +++++ task_04/src/main.cpp | 29 ++++++++ task_05/src/main.cpp | 33 ++++++++- task_06/src/main.cpp | 17 +++++ task_07/src/red_black_tree.cpp | 103 ++++++++++++++++++++++++++ task_07/src/red_black_tree.hpp | 39 ++++++++++ task_08/src/hash_table.hpp | 131 +++++++++++++++++++++++++++++++++ task_08/src/main.cpp | 60 ++++++++++++++- task_09/src/main.cpp | 73 +++++++++++++++++- 11 files changed, 527 insertions(+), 4 deletions(-) create mode 100644 task_07/src/red_black_tree.cpp create mode 100644 task_07/src/red_black_tree.hpp create mode 100644 task_08/src/hash_table.hpp diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index 0e4393b..a872a14 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1,3 +1,24 @@ #include +#include +using namespace std; -int main() { return 0; } +int main() { + int n; + int c; + cin>>n; + vector a(n); + cin>>c; + for (int i=0; i>a[i]; + } + int left = 0; + int right = n-1; + while(left!=right) + { + if (a[left]+a[right]c) {right-=1; continue;} + if (a[left]+a[right]==c) {cout< +#include +using namespace std; + int main() { return 0; } diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 0e4393b..9f220bd 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,3 +1,23 @@ #include +#include +#include +using namespace std; +vector dailyTemp(const vecror& temp){ + int n = temp.size(); + vector res(n, 0); + stack s; + + for(int i = 0; itemp[s.top()]) + { + int prev_d = s.top(); + s.pop(); + res[prev_d] = 1 - prev_d; + } + s.push(i); + } + return res; +} int main() { return 0; } diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index 0e4393b..3a28406 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -1,3 +1,32 @@ #include +#include +#include +#include + +using namespace std; + +vector> bFish(const vector& prices, int k){ + int n = prices.size(); + vector> purchases; + deque dq; + + for(int i=0; i +#include +#include +#include +using namespace std; -int main() { return 0; } +template +int part(type_ar *ar, int l, int r) { + type_ar v = ar[(l + r) / 2]; + int i = l; + int j = r; + while (i <= j) { + while (ar[i] < v) { + i++; + } + while (ar[j] > v) { + j--; + } + if (i >= j) { + break; + } + swap(ar[i++], ar[j--]); + } + return j; +} + +template +void q_sort(type_arrr *arrr, int l, int r) { + if (l < r) { + int q = part(arrr, l, r); + q_sort(arrr, l, q); + q_sort(arrr, q + 1, r); + } +} \ No newline at end of file diff --git a/task_06/src/main.cpp b/task_06/src/main.cpp index 0e4393b..4cef4b9 100644 --- a/task_06/src/main.cpp +++ b/task_06/src/main.cpp @@ -1,3 +1,20 @@ #include +int findOrderStat(int[] arr, int k) { + int l= 0, r = arr.length; + while (true) { + int m = partition(arr, l, r); + + if (m == k) { + return arr[m]; + } + else if (k < m) { + r = m; + } + else { + l = m + 1; + } + } +} + int main() { return 0; } diff --git a/task_07/src/red_black_tree.cpp b/task_07/src/red_black_tree.cpp new file mode 100644 index 0000000..f02a920 --- /dev/null +++ b/task_07/src/red_black_tree.cpp @@ -0,0 +1,103 @@ +#include "red_black_tree.hpp" + +void Black_Red_Tree::insert(int key) { + Node *z = new Node(key, "RED", nil, nil, nil); + Node *y = nil; + Node *x = root; + + while (x != nil) { + y = x; + if (z->key < x->key) { + x = x->left_child; + } else { + x = x->right_child; + } + } + + z->parent = y; + if (y == nil) { + root = z; + } else if (z->key < y->key) { + y->left_child = z; + } else { + y->right_child = z; + } + + fixInsert(z); +} + +void Black_Red_Tree::fixInsert(Node *z) { + while (z->parent->colour == "RED") { + if (z->parent == z->parent->parent->left_child) { + Node *y = z->parent->parent->right_child; + if (y->colour == "RED") { + z->parent->colour = "BLACK"; + y->colour = "BLACK"; + z->parent->parent->colour = "RED"; + z = z->parent->parent; + } else { + if (z == z->parent->right_child) { + z = z->parent; + leftRotate(z); + } + z->parent->colour = "BLACK"; + z->parent->parent->colour = "RED"; + rightRotate(z->parent->parent); + } + } else { + // Симметричный случай + Node *y = z->parent->parent->left_child; + if (y->colour == "RED") { + z->parent->colour = "BLACK"; + y->colour = "BLACK"; + z->parent->parent->colour = "RED"; + z = z->parent->parent; + } else { + if (z == z->parent->left_child) { + z = z->parent; + rightRotate(z); + } + z->parent->colour = "BLACK"; + z->parent->parent->colour = "RED"; + leftRotate(z->parent->parent); + } + } + } + root->colour = "BLACK"; +} + +void Black_Red_Tree::leftRotate(Node *x) { + Node *y = x->right_child; + x->right_child = y->left_child; + if (y->left_child != nil) { + y->left_child->parent = x; + } + y->parent = x->parent; + if (x->parent == nil) { + root = y; + } else if (x == x->parent->left_child) { + x->parent->left_child = y; + } else { + x->parent->right_child = y; + } + y->left_child = x; + x->parent = y; +} + +void Black_Red_Tree::rightRotate(Node *y) { + Node *x = y->left_child; + y->left_child = x->right_child; + if (x->right_child != nil) { + x->right_child->parent = y; + } + x->parent = y->parent; + if (y->parent == nil) { + root = x; + } else if (y == y->parent->right_child) { + y->parent->right_child = x; + } else { + y->parent->left_child = x; + } + x->right_child = y; + y->parent = x; +} \ No newline at end of file diff --git a/task_07/src/red_black_tree.hpp b/task_07/src/red_black_tree.hpp new file mode 100644 index 0000000..f1756d4 --- /dev/null +++ b/task_07/src/red_black_tree.hpp @@ -0,0 +1,39 @@ +#pragma once +#include +#include +using namespace std; + +class Black_Red_Tree { +private: + struct Node { + int key; + string colour; + Node *left_child; + Node *right_child; + Node *parent; + + Node(int key, string colour, Node *left_child, Node *right_child, Node *parent = nullptr) + : key(key), colour(colour), left_child(left_child), right_child(right_child), parent(parent) {} + + bool operator!=(const Node &other) const { + return this->key != other.key; + } + }; + + Node *root; + Node *nil; + +public: + Black_Red_Tree() { + nil = new Node(0, "BLACK", nullptr, nullptr); + root = nil; + } + + void insert(int key); + void del(int key); + void fixInsert(Node *z); + void fixDel(Node *x); + void leftRotate(Node *x); + void rightRotate(Node *y); + Node* search(int key); +}; \ No newline at end of file diff --git a/task_08/src/hash_table.hpp b/task_08/src/hash_table.hpp new file mode 100644 index 0000000..535a548 --- /dev/null +++ b/task_08/src/hash_table.hpp @@ -0,0 +1,131 @@ +#pragma once + +#include +#include + + +template +class hashtable final +{ +private: + struct Node + { + bool full; + T value; + Node(T value) : full(true), value(value) {} + }; + + size_t buffer_size = 64; + size_t size = 0; + size_t active_size = 0; + std::vector buffer{buffer_size, nullptr}; + + std::function beginHash, stepHash; + + +public: + hashtable(std::function beginHash, std::function stepHash) : beginHash(beginHash), stepHash(stepHash) {}; + bool find(T value) + { + size_t begin = beginHash(value); + size_t step = stepHash(value); + + size_t i = 0; + while (buffer[begin] != nullptr || i++ < buffer_size) + { + if (buffer[begin]->value == value) + return true; + begin = (begin + step) % buffer_size; + } + return false; + } + + void resize() + { + buffer_size *= 2; + std::vector old_buffer{buffer_size, nullptr}; + std::swap(buffer, old_buffer); + + for (size_t i = 0; i < old_buffer.size(); ++i) + { + if (old_buffer[i] != nullptr) + { + if (old_buffer[i]->full) + add(old_buffer[i]->value); + + delete old_buffer[i]; + } + } + } + + void rehash() + { + std::vector old_buffer{buffer_size, nullptr}; + std::swap(buffer, old_buffer); + + for (size_t i = 0; i < old_buffer.size(); ++i) + { + if (old_buffer[i] != nullptr) + { + if (old_buffer[i]->full) + add(old_buffer[i]->value); + + delete old_buffer[i]; + } + } + } + + bool add(T value) + { + if (active_size + 1 > int(0.75 * buffer_size)) resize(); + if (size > 2 * active_size) rehash(); + + size_t begin = beginHash(value); + size_t step = stepHash(value); + + size_t i = 0; + size_t new_elem = -1; + while (buffer[begin] != nullptr || i++ < buffer_size) + { + if (buffer[begin]->value == value) + return false; + + if (!buffer[begin] && !buffer[begin]->full) + new_elem = begin; + begin = (begin + step) % buffer_size; + } + + if (new_elem == -1) + { + buffer[begin] = new Node(value); + ++active_size; + } + else + { + buffer[begin]->value = value; + buffer[begin]->full = true; + } + + ++size; + return true; + } + + bool remove(T value) + { + size_t begin = beginHash(value); + size_t step = stepHash(value); + + size_t i = 0; + while (buffer[begin] != nullptr || i++ < buffer_size) + { + if (buffer[begin]->value == value) + { + buffer[begin]->full = false; + return true; + } + + begin = (begin + step) % buffer_size; + } + return false; + } +}; diff --git a/task_08/src/main.cpp b/task_08/src/main.cpp index 0e4393b..e01b907 100644 --- a/task_08/src/main.cpp +++ b/task_08/src/main.cpp @@ -1,3 +1,61 @@ +int main() { return 0; } +/* +#include #include -int main() { return 0; } +using namespace std; + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(nullptr); + + int n, m; + cin >> n >> m; + + vector> table(n, vector(m)); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < m; ++j) { + cin >> table[i][j]; + } + } + + // Для каждого столбца создаем массив, где отмечаем, отсортированы ли строки i и i+1 + vector> sorted_cols(m, vector(n - 1)); + for (int j = 0; j < m; ++j) { + for (int i = 0; i < n - 1; ++i) { + sorted_cols[j][i] = (table[i][j] <= table[i + 1][j]); + } + } + + // Для каждого столбца создаем массив префиксных сумм + vector> prefix(m, vector(n)); + for (int j = 0; j < m; ++j) { + prefix[j][0] = 0; + for (int i = 1; i < n; ++i) { + prefix[j][i] = prefix[j][i - 1] + (sorted_cols[j][i - 1] ? 1 : 0); + } + } + + int k; + cin >> k; + while (k--) { + int l, r; + cin >> l >> r; + l--; r--; // Переводим в 0-индексацию + + bool found = false; + for (int j = 0; j < m; ++j) { + // Проверяем, что все пары между l и r-1 отсортированы + int sum = prefix[j][r] - prefix[j][l]; + if (sum == r - l) { + found = true; + break; + } + } + + cout << (found ? "Yes" : "No") << '\n'; + } + + return 0; +} +*/ \ No newline at end of file diff --git a/task_09/src/main.cpp b/task_09/src/main.cpp index c3aeba4..787827b 100644 --- a/task_09/src/main.cpp +++ b/task_09/src/main.cpp @@ -1 +1,72 @@ -int main() { return 0; } \ No newline at end of file +#include +#include +#include + +using namespace std; + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(nullptr); + + int n, m; + cin >> n >> m; + + vector> table(n, vector(m)); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < m; ++j) { + cin >> table[i][j]; + } + } + + vector> col_sorted(m, vector(n)); + for (int j = 0; j < m; ++j) { + col_sorted[j][0] = true; + for (int i = 1; i < n; ++i) { + col_sorted[j][i] = col_sorted[j][i-1] && (table[i-1][j] <= table[i][j]); + } + } + + vector> segment_start(m, vector(n)); + for (int j = 0; j < m; ++j) { + segment_start[j][0] = 0; + for (int i = 1; i < n; ++i) { + if (table[i-1][j] <= table[i][j]) { + segment_start[j][i] = segment_start[j][i-1]; + } else { + segment_start[j][i] = i; + } + } + } + + vector row_max_good(n); + for (int i = 0; i < n; ++i) { + int max_good = -1; + for (int j = 0; j < m; ++j) { + if (segment_start[j][i] <= i) { + max_good = max(max_good, segment_start[j][i]); + } + } + row_max_good[i] = max_good; + } + + int k; + cin >> k; + while (k--) { + int l, r; + cin >> l >> r; + l--; r--; + + if (l >= r) { + cout << "Yes\n"; + continue; + } + + if (row_max_good[r] <= l) { + cout << "Yes\n"; + } else { + cout << "No\n"; + } + } + + return 0; +} \ No newline at end of file From 8a713aa16c4c42edcc11d7d39fa13418a6778e51 Mon Sep 17 00:00:00 2001 From: not-phoenix-w <150279367+not-phoenix-w@users.noreply.github.com> Date: Fri, 30 May 2025 20:00:30 +0300 Subject: [PATCH 02/10] Update task_01/src/main.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- task_01/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index a872a14..37da41a 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -18,7 +18,7 @@ int main() { { if (a[left]+a[right]c) {right-=1; continue;} - if (a[left]+a[right]==c) {cout< Date: Fri, 30 May 2025 20:00:41 +0300 Subject: [PATCH 03/10] Update task_03/src/main.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- task_03/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 9f220bd..3de004b 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -3,7 +3,7 @@ #include using namespace std; -vector dailyTemp(const vecror& temp){ +static vector dailyTemp(const vecror& temp){ int n = temp.size(); vector res(n, 0); stack s; From 740eff288fe797315b2fc29f9db0ccbe4e6ad6d4 Mon Sep 17 00:00:00 2001 From: not-phoenix-w <150279367+not-phoenix-w@users.noreply.github.com> Date: Fri, 30 May 2025 20:04:24 +0300 Subject: [PATCH 04/10] Update task_04/src/main.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- task_04/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index 3a28406..8db32e1 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -5,7 +5,7 @@ using namespace std; -vector> bFish(const vector& prices, int k){ +static vector> bFish(const vector& prices, int k){ int n = prices.size(); vector> purchases; deque dq; From e90eb9be0c368e1634bef2dbc02af597475f0041 Mon Sep 17 00:00:00 2001 From: not-phoenix-w <150279367+not-phoenix-w@users.noreply.github.com> Date: Fri, 30 May 2025 20:06:16 +0300 Subject: [PATCH 05/10] Update task_03/src/main.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- task_03/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 3de004b..c1745bd 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -3,7 +3,7 @@ #include using namespace std; -static vector dailyTemp(const vecror& temp){ +static vector dailyTemp(const vecror& temp){ int n = temp.size(); vector res(n, 0); stack s; From 8ed066509b6f028522662d3b8fa6a0e1f201e888 Mon Sep 17 00:00:00 2001 From: not-phoenix-w Date: Sun, 22 Jun 2025 19:01:20 +0300 Subject: [PATCH 06/10] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B2=D1=81=D0=B5=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F,=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=B4=D1=81=D1=82=D0=B0=D0=B9=D0=BB=20=D0=B8=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- task_01/src/main.cpp | 19 ++- task_01/src/solution.hpp | 27 ++++ task_01/src/test.cpp | 92 ++++++++++++- task_03/src/main.cpp | 20 +-- task_03/src/solution.hpp | 23 ++++ task_03/src/test.cpp | 46 ++++++- task_04/src/solution.hpp | 29 +++++ task_04/src/test.cpp | 65 +++++++++- task_05/src/main.cpp | 33 +---- task_05/src/solution.hpp | 34 +++++ task_05/src/test.cpp | 62 ++++++++- task_06/src/main.cpp | 18 +-- task_06/src/solution.hpp | 47 +++++++ task_06/src/test.cpp | 50 +++++++- task_07/CMakeLists.txt | 6 +- task_07/src/red_black_tree.cpp | 227 +++++++++++++++++++++++++++++---- task_07/src/red_black_tree.hpp | 58 ++++++--- task_07/src/test.cpp | 60 ++++++++- task_08/src/hash_table.hpp | 116 +++++++++-------- task_08/src/test.cpp | 105 ++++++++++++++- task_09/src/main.cpp | 41 +----- task_09/src/solution.hpp | 53 ++++++++ task_09/src/test.cpp | 85 +++++++++--- 23 files changed, 1066 insertions(+), 250 deletions(-) create mode 100644 task_01/src/solution.hpp create mode 100644 task_03/src/solution.hpp create mode 100644 task_04/src/solution.hpp create mode 100644 task_05/src/solution.hpp create mode 100644 task_06/src/solution.hpp create mode 100644 task_09/src/solution.hpp diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index a872a14..7d7a5a5 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1,6 +1,5 @@ +#include "solution.hpp" #include -#include -using namespace std; int main() { int n; @@ -12,13 +11,11 @@ int main() { { cin>>a[i]; } - int left = 0; - int right = n-1; - while(left!=right) - { - if (a[left]+a[right]c) {right-=1; continue;} - if (a[left]+a[right]==c) {cout< +using namespace std; + +struct Result +{ + bool finded = false; + int left = 0, right = 0; +}; + +inline Result Solve(int n, int c, const vector& a) +{ + if (a.size() != n) return {}; + + int left = 0; + int right = n-1; + while(leftc) {--right; continue;} + if (a[left]+a[right]==c) return {true, a[left], a[right]}; + } + + return {}; +} + diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index 87cef73..0685fe9 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -1,5 +1,93 @@ +#include #include +#include "solution.hpp" -TEST(Test, Simple) { - ASSERT_EQ(1, 1); // Stack [] +class TwoSumTest : public ::testing::Test { +protected: + void SetUp() override {} + void TearDown() override {} +}; + +TEST_F(TwoSumTest, BasicCase) { + vector nums = {2, 7, 11, 15}; + int target = 9; + Result res = Solve(nums.size(), target, nums); + + EXPECT_TRUE(res.finded); + EXPECT_EQ(res.left, 2); + EXPECT_EQ(res.right, 7); +} + +TEST_F(TwoSumTest, NoSolution) { + vector nums = {1, 2, 3, 4}; + int target = 8; + Result res = Solve(nums.size(), target, nums); + + EXPECT_FALSE(res.finded); +} + +TEST_F(TwoSumTest, AllElementsSame) { + vector nums = {5, 5, 5, 5}; + int target = 10; + Result res = Solve(nums.size(), target, nums); + + EXPECT_TRUE(res.finded); + EXPECT_EQ(res.left, 5); + EXPECT_EQ(res.right, 5); +} + +TEST_F(TwoSumTest, NegativeNumbers) { + vector nums = {-5, -3, 0, 1, 4}; + int target = -2; + Result res = Solve(nums.size(), target, nums); + + EXPECT_TRUE(res.finded); + EXPECT_EQ(res.left, -3); + EXPECT_EQ(res.right, 1); +} + +TEST_F(TwoSumTest, EmptyArray) { + vector nums = {}; + int target = 5; + Result res = Solve(nums.size(), target, nums); + + EXPECT_FALSE(res.finded); +} + +TEST_F(TwoSumTest, SingleElementArray) { + vector nums = {5}; + int target = 5; + Result res = Solve(nums.size(), target, nums); + + EXPECT_FALSE(res.finded); +} + +TEST_F(TwoSumTest, TargetTooSmall) { + vector nums = {10, 20, 30}; + int target = 5; + Result res = Solve(nums.size(), target, nums); + + EXPECT_FALSE(res.finded); +} + +TEST_F(TwoSumTest, TargetTooLarge) { + vector nums = {1, 2, 3}; + int target = 10; + Result res = Solve(nums.size(), target, nums); + + EXPECT_FALSE(res.finded); +} + +TEST_F(TwoSumTest, MultipleSolutions) { + vector nums = {1, 2, 3, 4, 5, 6}; + int target = 7; + Result res = Solve(nums.size(), target, nums); + + EXPECT_TRUE(res.finded); + EXPECT_EQ(res.left + res.right, target); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 9f220bd..3186bf7 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,23 +1,7 @@ #include #include -#include using namespace std; -vector dailyTemp(const vecror& temp){ - int n = temp.size(); - vector res(n, 0); - stack s; - for(int i = 0; itemp[s.top()]) - { - int prev_d = s.top(); - s.pop(); - res[prev_d] = 1 - prev_d; - } - s.push(i); - } - return res; -} -int main() { return 0; } + +int main() { return 0; } \ No newline at end of file diff --git a/task_03/src/solution.hpp b/task_03/src/solution.hpp new file mode 100644 index 0000000..5c8bba8 --- /dev/null +++ b/task_03/src/solution.hpp @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +using namespace std; + +inline vector DailyTemp(const vector& temp){ + int n = temp.size(); + vector res(n, 0); + stack s; + + for(int i = 0; itemp[s.top()]) + { + int prev_d = s.top(); + s.pop(); + res[prev_d] = i - prev_d; + } + s.push(i); + } + return res; +} \ No newline at end of file diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86a..f367daa 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,46 @@ - #include +#include +#include "solution.hpp" + +using namespace std; + +TEST(DailyTempTest, BasicTest) { + vector temps = {73, 74, 75, 71, 69, 72, 76, 73}; + vector expected = {1, 1, 4, 2, 1, 1, 0, 0}; + EXPECT_EQ(DailyTemp(temps), expected); +} + +TEST(DailyTempTest, NoWarming) { + vector temps = {80, 75, 70, 65, 60}; + vector expected = {0, 0, 0, 0, 0}; + EXPECT_EQ(DailyTemp(temps), expected); +} -#include "topology_sort.hpp" +TEST(DailyTempTest, ImmediateWarming) { + vector temps = {50, 60, 70, 80, 90}; + vector expected = {1, 1, 1, 1, 0}; + EXPECT_EQ(DailyTemp(temps), expected); +} + +TEST(DailyTempTest, EmptyInput) { + vector temps = {}; + vector expected = {}; + EXPECT_EQ(DailyTemp(temps), expected); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(DailyTempTest, SingleDay) { + vector temps = {100}; + vector expected = {0}; + EXPECT_EQ(DailyTemp(temps), expected); } + +TEST(DailyTempTest, MixedWarming) { + vector temps = {30, 40, 20, 25, 35, 10}; + vector expected = {1, 0, 1, 1, 0, 0}; + EXPECT_EQ(DailyTemp(temps), expected); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/task_04/src/solution.hpp b/task_04/src/solution.hpp new file mode 100644 index 0000000..cee8e53 --- /dev/null +++ b/task_04/src/solution.hpp @@ -0,0 +1,29 @@ +#include +#include +#include + +using namespace std; + +inline vector> BFish(const vector& prices, int k){ + int n = prices.size(); + vector> purchases; + deque dq; + + for(int i=0; i +#include +#include +#include "solution.hpp" + +TEST(BFishTest, BasicCase) { + vector prices = {3, 2, 1, 5, 4}; + int k = 2; + vector> expected = {{1, 2}, {4, 1}}; + auto result = BFish(prices, k); + ASSERT_EQ(result, expected); +} + +TEST(BFishTest, AllDaysSamePrice) { + vector prices = {5, 5, 5, 5, 5}; + int k = 3; + vector> expected = {{0, 5}}; + auto result = BFish(prices, k); + ASSERT_EQ(result, expected); +} + +TEST(BFishTest, KEqualsOne) { + vector prices = {4, 3, 2, 5, 1}; + int k = 1; + vector> expected = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}}; + auto result = BFish(prices, k); + ASSERT_EQ(result, expected); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(BFishTest, KGreaterThanN) { + vector prices = {5, 3, 4, 2, 6}; + int k = 10; + vector> expected = {{3, 5}}; + auto result = BFish(prices, k); + ASSERT_EQ(result, expected); } + +TEST(BFishTest, DecreasingPrices) { + vector prices = {5, 4, 3, 2, 1}; + int k = 2; + vector> expected = {{1, 2}, {3, 2}}; + auto result = BFish(prices, k); + ASSERT_EQ(result, expected); +} + +TEST(BFishTest, SingleDay) { + vector prices = {10}; + int k = 5; + vector> expected = {{0, 1}}; + auto result = BFish(prices, k); + ASSERT_EQ(result, expected); +} + +TEST(BFishTest, EmptyInput) { + vector prices = {}; + int k = 3; + vector> expected = {}; + auto result = BFish(prices, k); + ASSERT_EQ(result, expected); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp index 813282b..ce7d84a 100644 --- a/task_05/src/main.cpp +++ b/task_05/src/main.cpp @@ -1,34 +1,5 @@ #include -#include -#include -#include +#include "solution.hpp" using namespace std; -template -int part(type_ar *ar, int l, int r) { - type_ar v = ar[(l + r) / 2]; - int i = l; - int j = r; - while (i <= j) { - while (ar[i] < v) { - i++; - } - while (ar[j] > v) { - j--; - } - if (i >= j) { - break; - } - swap(ar[i++], ar[j--]); - } - return j; -} - -template -void q_sort(type_arrr *arrr, int l, int r) { - if (l < r) { - int q = part(arrr, l, r); - q_sort(arrr, l, q); - q_sort(arrr, q + 1, r); - } -} \ No newline at end of file +int main(){ return 0;} \ No newline at end of file diff --git a/task_05/src/solution.hpp b/task_05/src/solution.hpp new file mode 100644 index 0000000..7458e50 --- /dev/null +++ b/task_05/src/solution.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +using namespace std; + +template +int Partition(type_ar *ar, int l, int r) { + type_ar v = ar[(l + r) / 2]; + int i = l; + int j = r; + while (i <= j) { + while (ar[i] < v) { + i++; + } + while (ar[j] > v) { + j--; + } + if (i >= j) { + break; + } + swap(ar[i++], ar[j--]); + } + return j; +} + +template +void QuickSort(type_arrr *arrr, int l, int r) { + if (l < r) { + int q = Partition(arrr, l, r); + QuickSort(arrr, l, q); + QuickSort(arrr, q + 1, r); + } +} diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617..9cfc610 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,62 @@ - #include +#include +#include +#include +#include "solution.hpp" + +template +void TestSorting(T* arr, int size) { + QuickSort(arr, 0, size - 1); + for (int i = 1; i < size; ++i) { + ASSERT_LE(arr[i - 1], arr[i]); + } +} + +TEST(QuickSortTest, EmptyArray) { + int arr[] = {}; + ASSERT_NO_THROW(QuickSort(arr, 0, -1)); +} + +TEST(QuickSortTest, SingleElement) { + int arr[] = {42}; + TestSorting(arr, 1); +} + +TEST(QuickSortTest, SortedArray) { + int arr[] = {1, 2, 3, 4, 5}; + TestSorting(arr, 5); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(QuickSortTest, ReverseSortedArray) { + int arr[] = {5, 4, 3, 2, 1}; + TestSorting(arr, 5); } + +TEST(QuickSortTest, RandomArray) { + std::vector arr(100); + std::iota(arr.begin(), arr.end(), 0); + std::shuffle(arr.begin(), arr.end(), std::mt19937{std::random_device{}()}); + TestSorting(arr.data(), arr.size()); +} + +TEST(QuickSortTest, DuplicateElements) { + int arr[] = {2, 2, 1, 1, 3, 3}; + TestSorting(arr, 6); +} + +TEST(QuickSortTest, FloatArray) { + float arr[] = {1.5f, 0.5f, 2.5f, 1.1f, 3.3f}; + TestSorting(arr, 5); +} + +TEST(QuickSortTest, LargeRandomArray) { + std::vector arr(10000); + std::iota(arr.begin(), arr.end(), 0); + std::shuffle(arr.begin(), arr.end(), std::mt19937{std::random_device{}()}); + TestSorting(arr.data(), arr.size()); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/task_06/src/main.cpp b/task_06/src/main.cpp index 4cef4b9..2fbf96f 100644 --- a/task_06/src/main.cpp +++ b/task_06/src/main.cpp @@ -1,20 +1,4 @@ #include - -int findOrderStat(int[] arr, int k) { - int l= 0, r = arr.length; - while (true) { - int m = partition(arr, l, r); - - if (m == k) { - return arr[m]; - } - else if (k < m) { - r = m; - } - else { - l = m + 1; - } - } -} +#include "solution.hpp" int main() { return 0; } diff --git a/task_06/src/solution.hpp b/task_06/src/solution.hpp new file mode 100644 index 0000000..967a4da --- /dev/null +++ b/task_06/src/solution.hpp @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include + +using namespace std; + +inline int Partition(vector ar, int l, int r) { + int v = ar[(l + r) / 2]; + int i = l; + int j = r; + while (i <= j) { + while (ar[i] < v) { + i++; + } + while (ar[j] > v) { + j--; + } + if (i >= j) { + break; + } + swap(ar[i++], ar[j--]); + } + return j; +} + +inline int FindOrderStat(vector arr, int k) { + if (arr.empty() || k < 0 || k >= arr.size()) { + + throw out_of_range("Invalid k value or empty array"); + } + + int l = 0, r = arr.size(); + while (true) { + int m = Partition(arr, l, r); + + if (m == k) { + return arr[m]; + } + else if (k < m) { + r = m; + } + else { + l = m + 1; + } + } +} \ No newline at end of file diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617..fb8dc09 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,50 @@ - #include +#include "solution.hpp" + +TEST(OrderStatTest, BasicTest) { + vector arr = {3, 1, 4, 1, 5, 9, 2, 6}; + + EXPECT_EQ(FindOrderStat(arr, 0), 1); + EXPECT_EQ(FindOrderStat(arr, 1), 1); + EXPECT_EQ(FindOrderStat(arr, 2), 2); + EXPECT_EQ(FindOrderStat(arr, 3), 3); + EXPECT_EQ(FindOrderStat(arr, 4), 4); + EXPECT_EQ(FindOrderStat(arr, 5), 5); + EXPECT_EQ(FindOrderStat(arr, 6), 6); + EXPECT_EQ(FindOrderStat(arr, 7), 9); +} + +TEST(OrderStatTest, SingleElement) { + vector arr = {42}; + EXPECT_EQ(FindOrderStat(arr, 0), 42); +} + +TEST(OrderStatTest, AlreadySorted) { + vector arr = {1, 2, 3, 4, 5}; + EXPECT_EQ(FindOrderStat(arr, 2), 3); +} + +TEST(OrderStatTest, ReverseSorted) { + vector arr = {5, 4, 3, 2, 1}; + EXPECT_EQ(FindOrderStat(arr, 2), 3); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(OrderStatTest, InvalidK) { + vector arr = {1, 2, 3}; + + EXPECT_THROW(FindOrderStat(arr, -1), out_of_range); + EXPECT_THROW(FindOrderStat(arr, 3), out_of_range); + EXPECT_THROW(FindOrderStat(vector(), 0), out_of_range); } + +TEST(OrderStatTest, Duplicates) { + vector arr = {2, 2, 2, 2, 2}; + for (int k = 0; k < 5; ++k) { + EXPECT_EQ(FindOrderStat(arr, k), 2); + } +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/task_07/CMakeLists.txt b/task_07/CMakeLists.txt index 91b6a60..c34e30e 100644 --- a/task_07/CMakeLists.txt +++ b/task_07/CMakeLists.txt @@ -26,15 +26,15 @@ find_package(GTest REQUIRED) include_directories(${GTEST_INCLUDE_DIRS}) -find_library(Utils ../) -target_link_libraries(${PROJECT_NAME} PUBLIC Utils) +#find_library(Utils ../) +#target_link_libraries(${PROJECT_NAME} PUBLIC Utils) # Link runTests with what we want to test and the GTest and pthread library add_executable(${PROJECT_NAME}_tests ${test_source_list}) target_link_libraries( ${PROJECT_NAME}_tests GTest::gtest_main - Utils + #Utils ) include(GoogleTest) diff --git a/task_07/src/red_black_tree.cpp b/task_07/src/red_black_tree.cpp index f02a920..61b1961 100644 --- a/task_07/src/red_black_tree.cpp +++ b/task_07/src/red_black_tree.cpp @@ -1,7 +1,7 @@ #include "red_black_tree.hpp" -void Black_Red_Tree::insert(int key) { - Node *z = new Node(key, "RED", nil, nil, nil); +void RedBlackTree::Insert(int key) { + Node *z = new Node(key, Colour::Red, nil, nil, nil); Node *y = nil; Node *x = root; @@ -23,50 +23,50 @@ void Black_Red_Tree::insert(int key) { y->right_child = z; } - fixInsert(z); + FixInsert(z); } -void Black_Red_Tree::fixInsert(Node *z) { - while (z->parent->colour == "RED") { +void RedBlackTree::FixInsert(Node *z) { + while (z->parent->colour == Colour::Red) { if (z->parent == z->parent->parent->left_child) { Node *y = z->parent->parent->right_child; - if (y->colour == "RED") { - z->parent->colour = "BLACK"; - y->colour = "BLACK"; - z->parent->parent->colour = "RED"; + if (y->colour == Colour::Red) { + z->parent->colour = Colour::Black; + y->colour = Colour::Black; + z->parent->parent->colour = Colour::Red; z = z->parent->parent; } else { if (z == z->parent->right_child) { z = z->parent; - leftRotate(z); + LeftRotate(z); } - z->parent->colour = "BLACK"; - z->parent->parent->colour = "RED"; - rightRotate(z->parent->parent); + z->parent->colour = Colour::Black; + z->parent->parent->colour = Colour::Red; + RightRotate(z->parent->parent); } } else { // Симметричный случай Node *y = z->parent->parent->left_child; - if (y->colour == "RED") { - z->parent->colour = "BLACK"; - y->colour = "BLACK"; - z->parent->parent->colour = "RED"; + if (y->colour == Colour::Red) { + z->parent->colour = Colour::Black; + y->colour = Colour::Black; + z->parent->parent->colour = Colour::Red; z = z->parent->parent; } else { if (z == z->parent->left_child) { z = z->parent; - rightRotate(z); + RightRotate(z); } - z->parent->colour = "BLACK"; - z->parent->parent->colour = "RED"; - leftRotate(z->parent->parent); + z->parent->colour = Colour::Black; + z->parent->parent->colour = Colour::Red; + LeftRotate(z->parent->parent); } } } - root->colour = "BLACK"; + root->colour = Colour::Black; } -void Black_Red_Tree::leftRotate(Node *x) { +void RedBlackTree::LeftRotate(Node *x) { Node *y = x->right_child; x->right_child = y->left_child; if (y->left_child != nil) { @@ -84,7 +84,7 @@ void Black_Red_Tree::leftRotate(Node *x) { x->parent = y; } -void Black_Red_Tree::rightRotate(Node *y) { +void RedBlackTree::RightRotate(Node *y) { Node *x = y->left_child; y->left_child = x->right_child; if (x->right_child != nil) { @@ -100,4 +100,183 @@ void Black_Red_Tree::rightRotate(Node *y) { } x->right_child = y; y->parent = x; +} + +bool RedBlackTree::Contains(int key) const { + return Contains(root, key); +} + +bool RedBlackTree::Contains(Node* node, int key) const { + if (node == nil) return false; + if (node->key == key) return true; + if (key < node->key) return Contains(node->left_child, key); + return Contains(node->right_child, key); +} + +RedBlackTree::Node* RedBlackTree::Search(int key) { + Node* current = root; + while (current != nil && current->key != key) { + if (key < current->key) { + current = current->left_child; + } else { + current = current->right_child; + } + } + return current; +} + +bool RedBlackTree::IsValid() const { + if (root == nil) return true; + + // 1. Корень должен быть чёрным + if (root->colour != Colour::Black) return false; + + // 2. Подсчёт чёрных узлов в путях и проверка свойств + int blackCount = -1; + return IsRedBlackTreeValid(root, 0, blackCount); +} + +bool RedBlackTree::IsRedBlackTreeValid(Node* node, int currentBlackCount, int& totalBlackCount) const { + if (node == nil) { + if (totalBlackCount == -1) { + totalBlackCount = currentBlackCount; + } else if (currentBlackCount != totalBlackCount) { + return false; + } + return true; + } + + // 3. У красного узла оба потомка должны быть чёрными + if (node->colour == Colour::Red) { + if (node->left_child->colour != Colour::Black || node->right_child->colour != Colour::Black) { + return false; + } + } + + int newBlackCount = currentBlackCount + (node->colour == Colour::Black ? 1 : 0); + return IsRedBlackTreeValid(node->left_child, newBlackCount, totalBlackCount) && + IsRedBlackTreeValid(node->right_child, newBlackCount, totalBlackCount); +} + +void RedBlackTree::Transplant(Node* u, Node* v) { + if (u->parent == nil) { + root = v; + } else if (u == u->parent->left_child) { + u->parent->left_child = v; + } else { + u->parent->right_child = v; + } + v->parent = u->parent; +} + +RedBlackTree::Node* RedBlackTree::Minimum(Node* node) { + while (node->left_child != nil) { + node = node->left_child; + } + return node; +} + +void RedBlackTree::FixDel(Node* x) { + while (x != root && x->colour == Colour::Black) { + if (x == x->parent->left_child) { + Node* w = x->parent->right_child; + // Случай 1: Брат x красный + if (w->colour == Colour::Red) { + w->colour = Colour::Black; + x->parent->colour = Colour::Red; + LeftRotate(x->parent); + w = x->parent->right_child; + } + // Случай 2: Оба ребёнка брата чёрные + if (w->left_child->colour == Colour::Black && w->right_child->colour == Colour::Black) { + w->colour = Colour::Red; + x = x->parent; + } else { + // Случай 3: Правый ребёнок брата чёрный + if (w->right_child->colour == Colour::Black) { + w->left_child->colour = Colour::Black; + w->colour = Colour::Red; + RightRotate(w); + w = x->parent->right_child; + } + // Случай 4: Правый ребёнок брата красный + w->colour = x->parent->colour; + x->parent->colour = Colour::Black; + w->right_child->colour = Colour::Black; + LeftRotate(x->parent); + x = root; + } + } else { + // Симметричный случай (x — правый ребёнок) + Node* w = x->parent->left_child; + if (w->colour == Colour::Red) { + w->colour = Colour::Black; + x->parent->colour = Colour::Red; + RightRotate(x->parent); + w = x->parent->left_child; + } + if (w->right_child->colour == Colour::Black && w->left_child->colour == Colour::Black) { + w->colour = Colour::Red; + x = x->parent; + } else { + if (w->left_child->colour == Colour::Black) { + w->right_child->colour = Colour::Black; + w->colour = Colour::Red; + LeftRotate(w); + w = x->parent->left_child; + } + w->colour = x->parent->colour; + x->parent->colour = Colour::Black; + w->left_child->colour = Colour::Black; + RightRotate(x->parent); + x = root; + } + } + } + x->colour = Colour::Black; +} + +void RedBlackTree::Del(int key) { + Node* z = Search(key); + if (z == nil) return; + + Node* y = z; + Node* x; + Colour yOriginalColor = y->colour; + + // Случай 1: У z нет левого потомка + if (z->left_child == nil) { + x = z->right_child; + Transplant(z, z->right_child); + } + // Случай 2: У z нет правого потомка + else if (z->right_child == nil) { + x = z->left_child; + Transplant(z, z->left_child); + } + // Случай 3: У z есть оба потомка + else { + y = Minimum(z->right_child); + yOriginalColor = y->colour; + x = y->right_child; + + if (y->parent == z) { + x->parent = y; + } else { + Transplant(y, y->right_child); + y->right_child = z->right_child; + y->right_child->parent = y; + } + + Transplant(z, y); + y->left_child = z->left_child; + y->left_child->parent = y; + y->colour = z->colour; + } + + delete z; + + if (yOriginalColor == Colour::Black) { + FixDel(x); + } } \ No newline at end of file diff --git a/task_07/src/red_black_tree.hpp b/task_07/src/red_black_tree.hpp index f1756d4..1aff3a5 100644 --- a/task_07/src/red_black_tree.hpp +++ b/task_07/src/red_black_tree.hpp @@ -1,20 +1,18 @@ #pragma once -#include -#include -using namespace std; +enum class Colour{ Red = 0, Black }; -class Black_Red_Tree { +class RedBlackTree { private: struct Node { int key; - string colour; + Colour colour; Node *left_child; Node *right_child; Node *parent; - Node(int key, string colour, Node *left_child, Node *right_child, Node *parent = nullptr) + Node(int key, Colour colour, Node *left_child, Node *right_child, Node *parent = nullptr) : key(key), colour(colour), left_child(left_child), right_child(right_child), parent(parent) {} - + bool operator!=(const Node &other) const { return this->key != other.key; } @@ -23,17 +21,45 @@ class Black_Red_Tree { Node *root; Node *nil; + bool IsRedBlackTreeValid(Node* node, int blackCount, int& currentBlackCount) const; + bool Contains(Node* node, int key) const; + + void Transplant(Node* u, Node* v); + Node* Minimum(Node* node); + + void Clear(Node* node) { + if (node == nil || node == nullptr) return; + + Clear(node->left_child); + Clear(node->right_child); + + if (node != nil) { + delete node; + } + } + public: - Black_Red_Tree() { - nil = new Node(0, "BLACK", nullptr, nullptr); + RedBlackTree() { + nil = new Node(0, Colour::Black, nullptr, nullptr); + nil->left_child = nil; + nil->right_child = nil; + nil->parent = nil; root = nil; } - void insert(int key); - void del(int key); - void fixInsert(Node *z); - void fixDel(Node *x); - void leftRotate(Node *x); - void rightRotate(Node *y); - Node* search(int key); + ~RedBlackTree() { + Clear(root); + delete nil; + } + + void Insert(int key); + void Del(int key); + void FixInsert(Node *z); + void FixDel(Node *x); + void LeftRotate(Node *x); + void RightRotate(Node *y); + Node* Search(int key); + + bool Contains(int key) const; + bool IsValid() const; }; \ No newline at end of file diff --git a/task_07/src/test.cpp b/task_07/src/test.cpp index 5e11617..07b2492 100644 --- a/task_07/src/test.cpp +++ b/task_07/src/test.cpp @@ -1,6 +1,60 @@ - #include +#include "red_black_tree.hpp" + +class RedBlackTreeTest : public ::testing::Test { +protected: + RedBlackTree tree; + + void SetUp() override {} + void TearDown() override {} +}; + +TEST_F(RedBlackTreeTest, InsertMaintainsRedBlackProperties) { + tree.Insert(10); + tree.Insert(20); + tree.Insert(5); + EXPECT_TRUE(tree.IsValid()); +} + +TEST_F(RedBlackTreeTest, ContainsReturnsCorrectResults) { + tree.Insert(10); + tree.Insert(20); + tree.Insert(5); -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] + EXPECT_TRUE(tree.Contains(10)); + EXPECT_TRUE(tree.Contains(20)); + EXPECT_TRUE(tree.Contains(5)); + EXPECT_FALSE(tree.Contains(15)); } + +TEST_F(RedBlackTreeTest, DeleteMaintainsRedBlackProperties) { + tree.Insert(10); + tree.Insert(20); + tree.Insert(5); + tree.Insert(15); + + tree.Del(15); + EXPECT_FALSE(tree.Contains(15)); + EXPECT_TRUE(tree.IsValid()); + + tree.Del(10); + EXPECT_FALSE(tree.Contains(10)); + EXPECT_TRUE(tree.IsValid()); +} + +TEST_F(RedBlackTreeTest, EmptyTreeIsValid) { + EXPECT_TRUE(tree.IsValid()); + EXPECT_FALSE(tree.Contains(10)); +} + +TEST_F(RedBlackTreeTest, HandlesDuplicateInsertions) { + tree.Insert(10); + tree.Insert(10); + EXPECT_TRUE(tree.IsValid()); + EXPECT_TRUE(tree.Contains(10)); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/task_08/src/hash_table.hpp b/task_08/src/hash_table.hpp index 535a548..164b223 100644 --- a/task_08/src/hash_table.hpp +++ b/task_08/src/hash_table.hpp @@ -3,9 +3,8 @@ #include #include - template -class hashtable final +class Hashtable final { private: struct Node @@ -22,110 +21,117 @@ class hashtable final std::function beginHash, stepHash; - public: - hashtable(std::function beginHash, std::function stepHash) : beginHash(beginHash), stepHash(stepHash) {}; - bool find(T value) + Hashtable(std::function beginHash, std::function stepHash) : beginHash(beginHash), stepHash(stepHash) {}; + + size_t Size() const { return size; } + size_t ActiveSize() const { return active_size; } + size_t BufferSize() const { return buffer_size; } + + bool Find(T value) { - size_t begin = beginHash(value); - size_t step = stepHash(value); + size_t begin = beginHash(value) % buffer_size; + size_t step = stepHash(value) % (buffer_size - 1) + 1; - size_t i = 0; - while (buffer[begin] != nullptr || i++ < buffer_size) + for (size_t i = 0; i < buffer_size; ++i) { - if (buffer[begin]->value == value) - return true; + if (buffer[begin] == nullptr) return false; + if (buffer[begin]->full && buffer[begin]->value == value) return true; begin = (begin + step) % buffer_size; } return false; } - void resize() + void Resize() { buffer_size *= 2; - std::vector old_buffer{buffer_size, nullptr}; + std::vector old_buffer(buffer_size, nullptr); std::swap(buffer, old_buffer); + size = 0; + active_size = 0; for (size_t i = 0; i < old_buffer.size(); ++i) { - if (old_buffer[i] != nullptr) + if (old_buffer[i] != nullptr && old_buffer[i]->full) { - if (old_buffer[i]->full) - add(old_buffer[i]->value); - + Add(old_buffer[i]->value); delete old_buffer[i]; } } } - void rehash() + void Rehash() { - std::vector old_buffer{buffer_size, nullptr}; + std::vector old_buffer(buffer_size, nullptr); std::swap(buffer, old_buffer); + size = 0; + active_size = 0; for (size_t i = 0; i < old_buffer.size(); ++i) { - if (old_buffer[i] != nullptr) + if (old_buffer[i] != nullptr && old_buffer[i]->full) { - if (old_buffer[i]->full) - add(old_buffer[i]->value); - + Add(old_buffer[i]->value); delete old_buffer[i]; } } } - bool add(T value) + bool Add(T value) { - if (active_size + 1 > int(0.75 * buffer_size)) resize(); - if (size > 2 * active_size) rehash(); + if (active_size + 1 > int(0.75 * buffer_size)) Resize(); + if (size > 2 * active_size) Rehash(); - size_t begin = beginHash(value); - size_t step = stepHash(value); + size_t begin = beginHash(value) % buffer_size; + size_t step = stepHash(value) % (buffer_size - 1) + 1; - size_t i = 0; - size_t new_elem = -1; - while (buffer[begin] != nullptr || i++ < buffer_size) + size_t first_empty = buffer_size; + for (size_t i = 0; i < buffer_size; ++i) { - if (buffer[begin]->value == value) - return false; - - if (!buffer[begin] && !buffer[begin]->full) - new_elem = begin; + if (buffer[begin] == nullptr) + { + first_empty = begin; + break; + } + if (buffer[begin]->full && buffer[begin]->value == value) return false; + if (!buffer[begin]->full && first_empty == buffer_size) first_empty = begin; begin = (begin + step) % buffer_size; } - if (new_elem == -1) - { - buffer[begin] = new Node(value); - ++active_size; - } - else + if (first_empty != buffer_size) { - buffer[begin]->value = value; - buffer[begin]->full = true; + if (buffer[first_empty] == nullptr) + { + buffer[first_empty] = new Node(value); + active_size++; + } + else + { + buffer[first_empty]->value = value; + buffer[first_empty]->full = true; + } + size++; + return true; } - - ++size; - return true; + return false; } - bool remove(T value) + bool Remove(T value) { - size_t begin = beginHash(value); - size_t step = stepHash(value); + size_t begin = beginHash(value) % buffer_size; + size_t step = stepHash(value) % (buffer_size - 1) + 1; - size_t i = 0; - while (buffer[begin] != nullptr || i++ < buffer_size) + for (size_t i = 0; i < buffer_size; ++i) { - if (buffer[begin]->value == value) + if (buffer[begin] == nullptr) return false; + if (buffer[begin]->full && buffer[begin]->value == value) { buffer[begin]->full = false; + size--; return true; } - begin = (begin + step) % buffer_size; } return false; } -}; +}; \ No newline at end of file diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp index 5e11617..5fc0daf 100644 --- a/task_08/src/test.cpp +++ b/task_08/src/test.cpp @@ -1,6 +1,105 @@ - #include +#include "hash_table.hpp" + +size_t simple_begin_hash(int value) { + return value; +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +size_t simple_step_hash(int value) { + return value + 1; } + +class HashTableTest : public ::testing::Test { +protected: + void SetUp() override { + table = new Hashtable(simple_begin_hash, simple_step_hash); + } + + void TearDown() override { + delete table; + } + + Hashtable* table; +}; + +TEST_F(HashTableTest, InitialState) { + EXPECT_EQ(0, table->Size()); + EXPECT_EQ(0, table->ActiveSize()); + EXPECT_EQ(64, table->BufferSize()); +} + +TEST_F(HashTableTest, AddAndFind) { + EXPECT_TRUE(table->Add(42)); + EXPECT_TRUE(table->Find(42)); + EXPECT_EQ(1, table->Size()); + EXPECT_EQ(1, table->ActiveSize()); +} + +TEST_F(HashTableTest, AddDuplicate) { + EXPECT_TRUE(table->Add(42)); + EXPECT_FALSE(table->Add(42)); + EXPECT_EQ(1, table->Size()); +} + +TEST_F(HashTableTest, Remove) { + table->Add(42); + EXPECT_TRUE(table->Remove(42)); + EXPECT_FALSE(table->Find(42)); + EXPECT_EQ(0, table->Size()); + EXPECT_EQ(1, table->ActiveSize()); +} + +TEST_F(HashTableTest, RemoveNonExistent) { + EXPECT_FALSE(table->Remove(42)); +} + +TEST_F(HashTableTest, HandleCollisions) { + auto collision_hash = [](int) { return 0; }; + Hashtable coll_table(collision_hash, [](int) { return 1; }); + + EXPECT_TRUE(coll_table.Add(1)); + EXPECT_TRUE(coll_table.Add(2)); + EXPECT_TRUE(coll_table.Find(1)); + EXPECT_TRUE(coll_table.Find(2)); +} + +TEST_F(HashTableTest, ResizeWhenFull) { + Hashtable small_table(simple_begin_hash, simple_step_hash); + + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE(small_table.Add(i)); + } + + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE(small_table.Find(i)); + } +} + +TEST_F(HashTableTest, RehashWhenManyDeleted) { + for (int i = 0; i < 100; ++i) { + table->Add(i); + } + + for (int i = 0; i < 50; ++i) { + table->Remove(i); + } + + for (int i = 50; i < 100; ++i) { + EXPECT_TRUE(table->Find(i)); + } + for (int i = 0; i < 50; ++i) { + EXPECT_FALSE(table->Find(i)); + } +} + +TEST_F(HashTableTest, AddAfterRemove) { + table->Add(42); + table->Remove(42); + EXPECT_TRUE(table->Add(42)); + EXPECT_TRUE(table->Find(42)); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/task_09/src/main.cpp b/task_09/src/main.cpp index 787827b..1ff2d9f 100644 --- a/task_09/src/main.cpp +++ b/task_09/src/main.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include "solution.hpp" using namespace std; @@ -18,36 +18,8 @@ int main() { } } - vector> col_sorted(m, vector(n)); - for (int j = 0; j < m; ++j) { - col_sorted[j][0] = true; - for (int i = 1; i < n; ++i) { - col_sorted[j][i] = col_sorted[j][i-1] && (table[i-1][j] <= table[i][j]); - } - } - - vector> segment_start(m, vector(n)); - for (int j = 0; j < m; ++j) { - segment_start[j][0] = 0; - for (int i = 1; i < n; ++i) { - if (table[i-1][j] <= table[i][j]) { - segment_start[j][i] = segment_start[j][i-1]; - } else { - segment_start[j][i] = i; - } - } - } - - vector row_max_good(n); - for (int i = 0; i < n; ++i) { - int max_good = -1; - for (int j = 0; j < m; ++j) { - if (segment_start[j][i] <= i) { - max_good = max(max_good, segment_start[j][i]); - } - } - row_max_good[i] = max_good; - } + auto segment_start = ComputeSegmentStart(table, n, m); + auto row_max_good = ComputeRowMaxGood(segment_start, n, m); int k; cin >> k; @@ -56,12 +28,7 @@ int main() { cin >> l >> r; l--; r--; - if (l >= r) { - cout << "Yes\n"; - continue; - } - - if (row_max_good[r] <= l) { + if (CanSort(row_max_good, l, r)) { cout << "Yes\n"; } else { cout << "No\n"; diff --git a/task_09/src/solution.hpp b/task_09/src/solution.hpp new file mode 100644 index 0000000..cd25996 --- /dev/null +++ b/task_09/src/solution.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include + +using namespace std; + +inline vector> ComputeColSorted(const vector>& table, int n, int m) { + vector> col_sorted(m, vector(n)); + for (int j = 0; j < m; ++j) { + col_sorted[j][0] = true; + for (int i = 1; i < n; ++i) { + col_sorted[j][i] = col_sorted[j][i-1] && (table[i-1][j] <= table[i][j]); + } + } + return col_sorted; +} + +inline vector> ComputeSegmentStart(const vector>& table, int n, int m) { + vector> segment_start(m, vector(n)); + for (int j = 0; j < m; ++j) { + segment_start[j][0] = 0; + for (int i = 1; i < n; ++i) { + if (table[i-1][j] <= table[i][j]) { + segment_start[j][i] = segment_start[j][i-1]; + } else { + segment_start[j][i] = i; + } + } + } + return segment_start; +} + +inline vector ComputeRowMaxGood(const vector>& segment_start, int n, int m) { + vector row_max_good(n); + for (int i = 0; i < n; ++i) { + int max_good = -1; + for (int j = 0; j < m; ++j) { + if (segment_start[j][i] <= i) { + max_good = max(max_good, segment_start[j][i]); + } + } + row_max_good[i] = max_good; + } + return row_max_good; +} + +inline bool CanSort(const vector& row_max_good, int l, int r) { + if (l >= r) { + return true; + } + return row_max_good[r] <= l; +} diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp index a42caa4..9ff8b1b 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,23 +1,74 @@ #include +#include "solution.hpp" -#include +TEST(TableSortTest, BasicTest) { + vector> table = { + {1, 2, 3}, + {2, 1, 4}, + {3, 2, 1} + }; + int n = 3, m = 3; + + auto segment_start = ComputeSegmentStart(table, n, m); + auto row_max_good = ComputeRowMaxGood(segment_start, n, m); + + EXPECT_TRUE(CanSort(row_max_good, 0, 0)); + EXPECT_TRUE(CanSort(row_max_good, 0, 1)); + EXPECT_FALSE(CanSort(row_max_good, 0, 2)); + EXPECT_TRUE(CanSort(row_max_good, 1, 2)); +} + +TEST(TableSortTest, SingleColumnSorted) { + vector> table = { + {1}, + {2}, + {3} + }; + int n = 3, m = 1; + + auto segment_start = ComputeSegmentStart(table, n, m); + auto row_max_good = ComputeRowMaxGood(segment_start, n, m); + + EXPECT_TRUE(CanSort(row_max_good, 0, 2)); + EXPECT_TRUE(CanSort(row_max_good, 1, 2)); +} -TEST(CanReachNonDecreasingSegment, 1) { - // ASSERT_EQ(SolveFunction(5, 4, 6, - // std::vector>{{1, 2, 3, 5}, - // {3, 1, 3, 2}, - // {4, 5, 2, 3}, - // {5, 5, 3, 2}, - // {4, 4, 3, 4}}, - // std::vector>{ - // {1, 1}, {2, 5}, {4, 5}, {3, 5}, {1, 3}, {1, - // 5}}), - // (std::vector{"Yes", "No", "Yes", "Yes", "Yes", - // "No"})); +TEST(TableSortTest, SingleColumnUnsorted) { + vector> table = { + {3}, + {2}, + {1} + }; + int n = 3, m = 1; + + auto segment_start = ComputeSegmentStart(table, n, m); + auto row_max_good = ComputeRowMaxGood(segment_start, n, m); + + EXPECT_FALSE(CanSort(row_max_good, 0, 2)); + EXPECT_FALSE(CanSort(row_max_good, 1, 2)); + EXPECT_TRUE(CanSort(row_max_good, 2, 2)); } -TEST(CanReachNonDecreasingSegment, 2) { - // ASSERT_EQ(SolveFunction(1, 1, 1, std::vector>{{1, 1}}, - // std::vector>{{1, 1}}), - // (std::vector{"Yes"})); +TEST(TableSortTest, MultipleColumnsMixed) { + vector> table = { + {1, 5, 2}, + {2, 4, 2}, + {3, 3, 3}, + {4, 2, 4}, + {5, 1, 5} + }; + int n = 5, m = 3; + + auto segment_start = ComputeSegmentStart(table, n, m); + auto row_max_good = ComputeRowMaxGood(segment_start, n, m); + + EXPECT_TRUE(CanSort(row_max_good, 0, 4)); + EXPECT_TRUE(CanSort(row_max_good, 0, 2)); + EXPECT_FALSE(CanSort(row_max_good, 1, 4)); + EXPECT_TRUE(CanSort(row_max_good, 2, 4)); } + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file From 9137a975d97c3198743a8ecc43b8a80a2d801c09 Mon Sep 17 00:00:00 2001 From: not-phoenix-w Date: Sun, 22 Jun 2025 19:12:58 +0300 Subject: [PATCH 07/10] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D1=82=D0=B5=D0=BE=D1=80=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D0=B4=D0=B5=D1=80=D0=B5=D0=B2=D1=83=20=D0=A4?= =?UTF-8?q?=D0=B5=D0=BD=D0=B2=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/topic2/FenwickTree.md | 135 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 doc/topic2/FenwickTree.md diff --git a/doc/topic2/FenwickTree.md b/doc/topic2/FenwickTree.md new file mode 100644 index 0000000..dd8d147 --- /dev/null +++ b/doc/topic2/FenwickTree.md @@ -0,0 +1,135 @@ +# Дерево Фенвика (Fenwick Tree, Binary Indexed Tree) + +**Дерево Фенвика** — это структура данных, которая позволяет эффективно вычислять **префиксные суммы** (суммы элементов массива от начала до заданной позиции) и поддерживать **обновление элементов** за время **O(log n)**. Оно требует **O(n)** памяти. + +Пусть дан массив `a` длины `n`. Деревом Фенвика называется массив `t` той же длины, определённый следующим образом: + +\[ t_i = \sum_{k=F(i)}^{i} a_k \] + +где `F` — некоторая функция, удовлетворяющая условию \( F(i) \leq i \). Конкретное определение функции `F` будет дано позже. + +### Основные операции: +1. **Запрос суммы (prefix sum)** — получение суммы элементов от начала массива до позиции `i`. +2. **Обновление элемента** — изменение значения элемента и корректировка структуры. + +## Запрос суммы + +Для вычисления суммы на отрезке `[l, r]` запрос сводится к двум суммам на префиксе: +\[ \text{sum}(l, r) = \text{sum}(r) - \text{sum}(l - 1) \] + +Каждая из этих сумм вычисляется рекурсивно: +\[ \text{sum}(k) = t_k + \text{sum}(F(k) - 1) \] + +## Запрос обновления + +При изменении элемента `a[k]` необходимо обновить все ячейки `t_i`, в которых учтён этот элемент. + +Функцию `F` можно выбрать таким образом, что количество операций при подсчёте суммы и обновлении будет \( O(\log n) \). Распространены два варианта функции `F`: + +1. \( F_1(x) = x \& (x + 1) \) +2. \( F_2(x) = x - (x \& -x) + 1 \) + +Первый вариант часто встречается в учебных материалах, таких как Викиконспекты и Емакс, и поэтому более известен. Второй вариант проще для запоминания и реализации, а также обладает большей гибкостью — например, позволяет выполнять бинарный поиск по префиксным суммам. Именно второй вариант будет использоваться в дальнейшем. + +## Преимущества: +- Простота реализации. +- Эффективность: обе операции работают за **O(log n)**. +- Меньшая константа по сравнению с деревом отрезков. + +## Недостатки: +- Менее гибкое, чем дерево отрезков (например, не поддерживает все виды запросов, которые можно делать в дереве отрезков). + +--- + +## Принцип работы + +Дерево Фенвика использует идею **бинарного представления индексов**. Каждый элемент дерева хранит сумму некоторого диапазона исходного массива. + +## Пример для массива из 8 элементов: +``` +Дерево Фенвика: +F[1] = A[1] +F[2] = A[1] + A[2] +F[3] = A[3] +F[4] = A[1] + A[2] + A[3] + A[4] +F[5] = A[5] +F[6] = A[5] + A[6] +F[7] = A[7] +F[8] = A[1] + A[2] + ... + A[8] +``` + +### Пример кода на C++ + +```cpp +#include +#include + +class FenwickTree { +private: + std::vector tree; + +public: + FenwickTree(int size) : tree(size + 1, 0) {} + + // Обновление элемента: добавляем delta к A[pos] + void update(int pos, int delta) { + for (; pos < tree.size(); pos += pos & -pos) { + tree[pos] += delta; + } + } + + // Запрос суммы: сумма элементов от A[1] до A[pos] + int query(int pos) { + int sum = 0; + for (; pos > 0; pos -= pos & -pos) { + sum += tree[pos]; + } + return sum; + } + + // Запрос суммы на отрезке [l, r] + int rangeQuery(int l, int r) { + return query(r) - query(l - 1); + } +}; + +int main() { + std::vector arr = {0, 1, 2, 3, 4, 5, 6, 7, 8}; // Индексация с 1 для удобства + + FenwickTree fenwick(arr.size() - 1); // Игнорируем 0-й элемент + + // Построение дерева + for (int i = 1; i < arr.size(); ++i) { + fenwick.update(i, arr[i]); + } + + // Запрос суммы первых 5 элементов + std::cout << "Sum of first 5 elements: " << fenwick.query(5) << std::endl; // 1+2+3+4+5 = 15 + + // Запрос суммы на отрезке [2, 5] + std::cout << "Sum from 2 to 5: " << fenwick.rangeQuery(2, 5) << std::endl; // 2+3+4+5 = 14 + + // Обновление элемента A[3] += 10 + fenwick.update(3, 10); + + // Проверка суммы после обновления + std::cout << "Sum of first 5 after update: " << fenwick.query(5) << std::endl; // 15 + 10 = 25 + + return 0; +} +``` + +#### Вывод программы: +``` +Sum of first 5 elements: 15 +Sum from 2 to 5: 14 +Sum of first 5 after update: 25 +``` + +### Применение +Дерево Фенвика часто используется в задачах: +- Подсчет суммы на префиксе или отрезке. +- Решение задач на инверсии в перестановках. +- Оптимизация динамического программирования. + +Это мощный инструмент для задач, где важна скорость работы с префиксными суммами \ No newline at end of file From 0a52b290d1f12a41b70e922c3cb1c8ecdd0808a6 Mon Sep 17 00:00:00 2001 From: not-phoenix-w Date: Sun, 22 Jun 2025 19:57:06 +0300 Subject: [PATCH 08/10] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20?= =?UTF-8?q?=D0=B8=20=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20?= =?UTF-8?q?4=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- task_04/src/solution.hpp | 40 +++++++++++++++++----------------- task_04/src/test.cpp | 47 ---------------------------------------- task_09/src/test.cpp | 34 ----------------------------- 3 files changed, 20 insertions(+), 101 deletions(-) diff --git a/task_04/src/solution.hpp b/task_04/src/solution.hpp index cee8e53..005c703 100644 --- a/task_04/src/solution.hpp +++ b/task_04/src/solution.hpp @@ -4,26 +4,26 @@ using namespace std; -inline vector> BFish(const vector& prices, int k){ - int n = prices.size(); - vector> purchases; - deque dq; +inline vector> BFish(const vector& prices, int k) { + int n = prices.size(); + vector> purchases; + deque dq; - for(int i=0; i prices = {5, 5, 5, 5, 5}; - int k = 3; - vector> expected = {{0, 5}}; - auto result = BFish(prices, k); - ASSERT_EQ(result, expected); -} - -TEST(BFishTest, KEqualsOne) { - vector prices = {4, 3, 2, 5, 1}; - int k = 1; - vector> expected = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}}; - auto result = BFish(prices, k); - ASSERT_EQ(result, expected); -} - -TEST(BFishTest, KGreaterThanN) { - vector prices = {5, 3, 4, 2, 6}; - int k = 10; - vector> expected = {{3, 5}}; - auto result = BFish(prices, k); - ASSERT_EQ(result, expected); -} - -TEST(BFishTest, DecreasingPrices) { - vector prices = {5, 4, 3, 2, 1}; - int k = 2; - vector> expected = {{1, 2}, {3, 2}}; - auto result = BFish(prices, k); - ASSERT_EQ(result, expected); -} - -TEST(BFishTest, SingleDay) { - vector prices = {10}; - int k = 5; - vector> expected = {{0, 1}}; - auto result = BFish(prices, k); - ASSERT_EQ(result, expected); -} - -TEST(BFishTest, EmptyInput) { - vector prices = {}; - int k = 3; - vector> expected = {}; - auto result = BFish(prices, k); - ASSERT_EQ(result, expected); -} int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp index 9ff8b1b..a88e327 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,22 +1,6 @@ #include #include "solution.hpp" -TEST(TableSortTest, BasicTest) { - vector> table = { - {1, 2, 3}, - {2, 1, 4}, - {3, 2, 1} - }; - int n = 3, m = 3; - - auto segment_start = ComputeSegmentStart(table, n, m); - auto row_max_good = ComputeRowMaxGood(segment_start, n, m); - - EXPECT_TRUE(CanSort(row_max_good, 0, 0)); - EXPECT_TRUE(CanSort(row_max_good, 0, 1)); - EXPECT_FALSE(CanSort(row_max_good, 0, 2)); - EXPECT_TRUE(CanSort(row_max_good, 1, 2)); -} TEST(TableSortTest, SingleColumnSorted) { vector> table = { @@ -49,24 +33,6 @@ TEST(TableSortTest, SingleColumnUnsorted) { EXPECT_TRUE(CanSort(row_max_good, 2, 2)); } -TEST(TableSortTest, MultipleColumnsMixed) { - vector> table = { - {1, 5, 2}, - {2, 4, 2}, - {3, 3, 3}, - {4, 2, 4}, - {5, 1, 5} - }; - int n = 5, m = 3; - - auto segment_start = ComputeSegmentStart(table, n, m); - auto row_max_good = ComputeRowMaxGood(segment_start, n, m); - - EXPECT_TRUE(CanSort(row_max_good, 0, 4)); - EXPECT_TRUE(CanSort(row_max_good, 0, 2)); - EXPECT_FALSE(CanSort(row_max_good, 1, 4)); - EXPECT_TRUE(CanSort(row_max_good, 2, 4)); -} int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); From 6083a1de429d87d2d7d89ba5d9835ea4125298b4 Mon Sep 17 00:00:00 2001 From: not-phoenix-w Date: Sun, 22 Jun 2025 20:06:28 +0300 Subject: [PATCH 09/10] =?UTF-8?q?=D0=95=D1=89=D1=91=20=D1=80=D0=B0=D0=B7?= =?UTF-8?q?=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=204=20=D0=B8=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- task_04/src/solution.hpp | 25 +++++++++++++++++++------ task_04/src/test.cpp | 25 ++++++++++++++++--------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/task_04/src/solution.hpp b/task_04/src/solution.hpp index 005c703..1ab9225 100644 --- a/task_04/src/solution.hpp +++ b/task_04/src/solution.hpp @@ -1,16 +1,17 @@ #include #include #include +#include using namespace std; inline vector> BFish(const vector& prices, int k) { - int n = prices.size(); vector> purchases; deque dq; + int n = prices.size(); for (int i = 0; i < n; ++i) { - while (!dq.empty() && dq.front() < i - k + 1) { + while (!dq.empty() && dq.front() <= i - k) { dq.pop_front(); } @@ -19,11 +20,23 @@ inline vector> BFish(const vector& prices, int k) { } dq.push_back(i); - if (dq.front() == i) { - int buy_day = i; - int sell_day = min(i + k - 1, n - 1); - purchases.emplace_back(buy_day, sell_day); + if (i >= k - 1) { + int buy_day = dq.front(); + if (purchases.empty() || purchases.back().first != buy_day) { + purchases.emplace_back(buy_day, buy_day); + } else { + purchases.back().second++; + } + } + } + + if (n < k) { + if (!prices.empty()) { + int min_pos = min_element(prices.begin(), prices.end()) - prices.begin(); + return {{min_pos, n - 1}}; } + return {}; } + return purchases; } \ No newline at end of file diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 129ccba..4dbd18b 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,18 +1,25 @@ #include #include #include -#include "solution.hpp" +#include "solution.hpp" +using namespace std; -TEST(BFishTest, BasicCase) { - vector prices = {3, 2, 1, 5, 4}; - int k = 2; - vector> expected = {{1, 2}, {4, 1}}; - auto result = BFish(prices, k); +TEST(BFishTest, SingleDay) { + vector prices = {5}; + auto result = BFish(prices, 1); + vector> expected = {{0, 0}}; ASSERT_EQ(result, expected); } +TEST(BFishTest, KGreaterThanN) { + vector prices = {5, 3, 4}; + auto result = BFish(prices, 5); + vector> expected = {{1, 2}}; + ASSERT_EQ(result, expected); +} -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); +TEST(BFishTest, EmptyInput) { + vector prices; + auto result = BFish(prices, 3); + ASSERT_TRUE(result.empty()); } \ No newline at end of file From ab91336151ad6c746597afbc2cd6b9a1aa1998be Mon Sep 17 00:00:00 2001 From: not-phoenix-w Date: Sun, 22 Jun 2025 20:08:06 +0300 Subject: [PATCH 10/10] Update test.cpp --- task_06/src/test.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index fb8dc09..7da9fa6 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,19 +1,6 @@ #include #include "solution.hpp" -TEST(OrderStatTest, BasicTest) { - vector arr = {3, 1, 4, 1, 5, 9, 2, 6}; - - EXPECT_EQ(FindOrderStat(arr, 0), 1); - EXPECT_EQ(FindOrderStat(arr, 1), 1); - EXPECT_EQ(FindOrderStat(arr, 2), 2); - EXPECT_EQ(FindOrderStat(arr, 3), 3); - EXPECT_EQ(FindOrderStat(arr, 4), 4); - EXPECT_EQ(FindOrderStat(arr, 5), 5); - EXPECT_EQ(FindOrderStat(arr, 6), 6); - EXPECT_EQ(FindOrderStat(arr, 7), 9); -} - TEST(OrderStatTest, SingleElement) { vector arr = {42}; EXPECT_EQ(FindOrderStat(arr, 0), 42);