diff --git a/.gitignore b/.gitignore index cb287df..4e17eaf 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ _deps *.out *.app +build \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ca284a3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "cmake.configureOnOpen": true, + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "files.associations": { + "climits": "cpp", + "sstream": "cpp", + "compare": "cpp" + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..fc10398 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++.exe 生成活动文件", + "command": "C:\\mingw64\\bin\\g++.exe", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}\\${fileBasenameNoExtension}.exe" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "调试器生成的任务。" + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1e80bc4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.10) +project(hello_algo CXX) + +set(CMAKE_CXX_STANDARD 11) + +include_directories(./include) + +add_subdirectory(chapter_computational_complexity) +add_subdirectory(chapter_array_and_linkedlist) +add_subdirectory(chapter_stack_and_queue) +add_subdirectory(chapter_hashing) +add_subdirectory(chapter_tree) +add_subdirectory(chapter_heap) +add_subdirectory(chapter_graph) +add_subdirectory(chapter_searching) +add_subdirectory(chapter_sorting) +add_subdirectory(chapter_divide_and_conquer) +add_subdirectory(chapter_backtracking) +add_subdirectory(chapter_dynamic_programming) +add_subdirectory(chapter_greedy) diff --git a/chapter_array_and_linkedlist/CMakeLists.txt b/chapter_array_and_linkedlist/CMakeLists.txt new file mode 100644 index 0000000..2e933e0 --- /dev/null +++ b/chapter_array_and_linkedlist/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(array array.cpp) +add_executable(linked_list linked_list.cpp) +add_executable(list list.cpp) +add_executable(my_list my_list.cpp) diff --git a/chapter_array_and_linkedlist/array.cpp b/chapter_array_and_linkedlist/array.cpp new file mode 100644 index 0000000..538a2e1 --- /dev/null +++ b/chapter_array_and_linkedlist/array.cpp @@ -0,0 +1,113 @@ +/** + * File: array.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Ԫ */ +int randomAccess(int *nums, int size) { + // [0, size) ȡһ + int randomIndex = rand() % size; + // ȡԪ + int randomNum = nums[randomIndex]; + return randomNum; +} + +/* չ鳤 */ +int *extend(int *nums, int size, int enlarge) { + // ʼһչȺ + int *res = new int[size + enlarge]; + // ԭеԪظƵ + for (int i = 0; i < size; i++) { + res[i] = nums[i]; + } + // ͷڴ + delete[] nums; + // չ + return res; +} + +/* index Ԫ num */ +void insert(int *nums, int size, int num, int index) { + // index Լ֮Ԫƶһλ + for (int i = size - 1; i > index; i--) { + nums[i] = nums[i - 1]; + } + // num index Ԫ + nums[index] = num; +} + +/* ɾ index Ԫ */ +void remove(int *nums, int size, int index) { + // index ֮Ԫǰƶһλ + for (int i = index; i < size - 1; i++) { + nums[i] = nums[i + 1]; + } +} + +/* */ +void traverse(int *nums, int size) { + int count = 0; + // ͨ + for (int i = 0; i < size; i++) { + count += nums[i]; + } +} + +/* вָԪ */ +int find(int *nums, int size, int target) { + for (int i = 0; i < size; i++) { + if (nums[i] == target) + return i; + } + return -1; +} + +/* Driver Code */ +int main() { + /* ʼ */ + int size = 5; + int *arr = new int[size]; + cout << " arr = "; + printArray(arr, size); + + int *nums = new int[size]{1, 3, 2, 5, 4}; + cout << " nums = "; + printArray(nums, size); + + /* */ + int randomNum = randomAccess(nums, size); + cout << " nums лȡԪ " << randomNum << endl; + + /* չ */ + int enlarge = 3; + nums = extend(nums, size, enlarge); + size += enlarge; + cout << "鳤չ 8 õ nums = "; + printArray(nums, size); + + /* Ԫ */ + insert(nums, size, 6, 3); + cout << " 3 6 õ nums = "; + printArray(nums, size); + + /* ɾԪ */ + remove(nums, size, 2); + cout << "ɾ 2 Ԫأõ nums = "; + printArray(nums, size); + + /* */ + traverse(nums, size); + + /* Ԫ */ + int index = find(nums, size, 3); + cout << " nums вԪ 3 õ = " << index << endl; + + // ͷڴ + delete[] arr; + delete[] nums; + + return 0; +} diff --git a/chapter_array_and_linkedlist/linked_list.cpp b/chapter_array_and_linkedlist/linked_list.cpp new file mode 100644 index 0000000..3304ead --- /dev/null +++ b/chapter_array_and_linkedlist/linked_list.cpp @@ -0,0 +1,89 @@ +/** + * File: linked_list.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Ľڵ n0 ֮ڵ P */ +void insert(ListNode *n0, ListNode *P) { + ListNode *n1 = n0->next; + P->next = n1; + n0->next = P; +} + +/* ɾĽڵ n0 ֮׸ڵ */ +void remove(ListNode *n0) { + if (n0->next == nullptr) + return; + // n0 -> P -> n1 + ListNode *P = n0->next; + ListNode *n1 = P->next; + n0->next = n1; + // ͷڴ + delete P; +} + +/* Ϊ index Ľڵ */ +ListNode *access(ListNode *head, int index) { + for (int i = 0; i < index; i++) { + if (head == nullptr) + return nullptr; + head = head->next; + } + return head; +} + +/* вֵΪ target ׸ڵ */ +int find(ListNode *head, int target) { + int index = 0; + while (head != nullptr) { + if (head->val == target) + return index; + head = head->next; + index++; + } + return -1; +} + +/* Driver Code */ +int main() { + /* ʼ */ + // ʼڵ + ListNode *n0 = new ListNode(1); + ListNode *n1 = new ListNode(3); + ListNode *n2 = new ListNode(2); + ListNode *n3 = new ListNode(5); + ListNode *n4 = new ListNode(4); + // ڵ֮ + n0->next = n1; + n1->next = n2; + n2->next = n3; + n3->next = n4; + cout << "ʼΪ" << endl; + printLinkedList(n0); + + /* ڵ */ + insert(n0, new ListNode(0)); + cout << "ڵΪ" << endl; + printLinkedList(n0); + + /* ɾڵ */ + remove(n0); + cout << "ɾڵΪ" << endl; + printLinkedList(n0); + + /* ʽڵ */ + ListNode *node = access(n0, 3); + cout << " 3 Ľڵֵ = " << node->val << endl; + + /* ҽڵ */ + int index = find(n0, 2); + cout << "ֵΪ 2 Ľڵ = " << index << endl; + + // ͷڴ + freeMemoryLinkedList(n0); + + return 0; +} diff --git a/chapter_array_and_linkedlist/list.cpp b/chapter_array_and_linkedlist/list.cpp new file mode 100644 index 0000000..4029173 --- /dev/null +++ b/chapter_array_and_linkedlist/list.cpp @@ -0,0 +1,72 @@ +/** + * File: list.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Driver Code */ +int main() { + /* ʼб */ + vector nums = {1, 3, 2, 5, 4}; + cout << "б nums = "; + printVector(nums); + + /* Ԫ */ + int num = nums[1]; + cout << " 1 Ԫأõ num = " << num << endl; + + /* Ԫ */ + nums[1] = 0; + cout << " 1 ԪظΪ 0 õ nums = "; + printVector(nums); + + /* б */ + nums.clear(); + cout << "б nums = "; + printVector(nums); + + /* βԪ */ + nums.push_back(1); + nums.push_back(3); + nums.push_back(2); + nums.push_back(5); + nums.push_back(4); + cout << "Ԫغ nums = "; + printVector(nums); + + /* мԪ */ + nums.insert(nums.begin() + 3, 6); + cout << " 3 6 õ nums = "; + printVector(nums); + + /* ɾԪ */ + nums.erase(nums.begin() + 3); + cout << "ɾ 3 Ԫأõ nums = "; + printVector(nums); + + /* ͨб */ + int count = 0; + for (int i = 0; i < nums.size(); i++) { + count += nums[i]; + } + /* ֱӱбԪ */ + count = 0; + for (int x : nums) { + count += x; + } + + /* ƴб */ + vector nums1 = {6, 8, 7, 10, 9}; + nums.insert(nums.end(), nums1.begin(), nums1.end()); + cout << "б nums1 ƴӵ nums ֮󣬵õ nums = "; + printVector(nums); + + /* б */ + sort(nums.begin(), nums.end()); + cout << "б nums = "; + printVector(nums); + + return 0; +} diff --git a/chapter_array_and_linkedlist/my_list.cpp b/chapter_array_and_linkedlist/my_list.cpp new file mode 100644 index 0000000..af35a70 --- /dev/null +++ b/chapter_array_and_linkedlist/my_list.cpp @@ -0,0 +1,171 @@ +/** + * File: my_list.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* б */ +class MyList { + private: + int *arr; // 飨洢бԪأ + int arrCapacity = 10; // б + int arrSize = 0; // бȣǰԪ + int extendRatio = 2; // ÿбݵı + + public: + /* 췽 */ + MyList() { + arr = new int[arrCapacity]; + } + + /* */ + ~MyList() { + delete[] arr; + } + + /* ȡбȣǰԪ*/ + int size() { + return arrSize; + } + + /* ȡб */ + int capacity() { + return arrCapacity; + } + + /* Ԫ */ + int get(int index) { + // Խ磬׳쳣ͬ + if (index < 0 || index >= size()) + throw out_of_range("Խ"); + return arr[index]; + } + + /* Ԫ */ + void set(int index, int num) { + if (index < 0 || index >= size()) + throw out_of_range("Խ"); + arr[index] = num; + } + + /* βԪ */ + void add(int num) { + // Ԫʱݻ + if (size() == capacity()) + extendCapacity(); + arr[size()] = num; + // Ԫ + arrSize++; + } + + /* мԪ */ + void insert(int index, int num) { + if (index < 0 || index >= size()) + throw out_of_range("Խ"); + // Ԫʱݻ + if (size() == capacity()) + extendCapacity(); + // index Լ֮Ԫضƶһλ + for (int j = size() - 1; j >= index; j--) { + arr[j + 1] = arr[j]; + } + arr[index] = num; + // Ԫ + arrSize++; + } + + /* ɾԪ */ + int remove(int index) { + if (index < 0 || index >= size()) + throw out_of_range("Խ"); + int num = arr[index]; + // index ֮Ԫضǰƶһλ + for (int j = index; j < size() - 1; j++) { + arr[j] = arr[j + 1]; + } + // Ԫ + arrSize--; + // رɾԪ + return num; + } + + /* б */ + void extendCapacity() { + // ½һΪԭ extendRatio + int newCapacity = capacity() * extendRatio; + int *tmp = arr; + arr = new int[newCapacity]; + // ԭеԪظƵ + for (int i = 0; i < size(); i++) { + arr[i] = tmp[i]; + } + // ͷڴ + delete[] tmp; + arrCapacity = newCapacity; + } + + /* бתΪ Vector ڴӡ */ + vector toVector() { + // תЧȷΧڵбԪ + vector vec(size()); + for (int i = 0; i < size(); i++) { + vec[i] = arr[i]; + } + return vec; + } +}; + +/* Driver Code */ +int main() { + /* ʼб */ + MyList *nums = new MyList(); + /* βԪ */ + nums->add(1); + nums->add(3); + nums->add(2); + nums->add(5); + nums->add(4); + cout << "б nums = "; + vector vec = nums->toVector(); + printVector(vec); + cout << " = " << nums->capacity() << " = " << nums->size() << endl; + + /* мԪ */ + nums->insert(3, 6); + cout << " 3 6 õ nums = "; + vec = nums->toVector(); + printVector(vec); + + /* ɾԪ */ + nums->remove(3); + cout << "ɾ 3 Ԫأõ nums = "; + vec = nums->toVector(); + printVector(vec); + + /* Ԫ */ + int num = nums->get(1); + cout << " 1 Ԫأõ num = " << num << endl; + + /* Ԫ */ + nums->set(1, 0); + cout << " 1 ԪظΪ 0 õ nums = "; + vec = nums->toVector(); + printVector(vec); + + /* ݻ */ + for (int i = 0; i < 10; i++) { + // i = 5 ʱбȽбʱݻ + nums->add(i); + } + cout << "ݺб nums = "; + vec = nums->toVector(); + printVector(vec); + cout << " = " << nums->capacity() << " = " << nums->size() << endl; + + // ͷڴ + delete nums; + + return 0; +} diff --git a/chapter_backtracking/CMakeLists.txt b/chapter_backtracking/CMakeLists.txt new file mode 100644 index 0000000..6c271e3 --- /dev/null +++ b/chapter_backtracking/CMakeLists.txt @@ -0,0 +1,10 @@ +add_executable(preorder_traversal_i_compact preorder_traversal_i_compact.cpp) +add_executable(preorder_traversal_ii_compact preorder_traversal_ii_compact.cpp) +add_executable(preorder_traversal_iii_compact preorder_traversal_iii_compact.cpp) +add_executable(preorder_traversal_iii_template preorder_traversal_iii_template.cpp) +add_executable(permutations_i permutations_i.cpp) +add_executable(permutations_ii permutations_ii.cpp) +add_executable(n_queens n_queens.cpp) +add_executable(subset_sum_i_naive subset_sum_i_naive.cpp) +add_executable(subset_sum_i subset_sum_i.cpp) +add_executable(subset_sum_ii subset_sum_ii.cpp) diff --git a/chapter_backtracking/n_queens.cpp b/chapter_backtracking/n_queens.cpp new file mode 100644 index 0000000..1e27986 --- /dev/null +++ b/chapter_backtracking/n_queens.cpp @@ -0,0 +1,65 @@ +/** + * File: n_queens.cpp + * Created Time: 2023-05-04 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* 㷨n ʺ */ +void backtrack(int row, int n, vector> &state, vector>> &res, vector &cols, + vector &diags1, vector &diags2) { + // ʱ¼ + if (row == n) { + res.push_back(state); + return; + } + // + for (int col = 0; col < n; col++) { + // øӶӦԽߺʹζԽ + int diag1 = row - col + n - 1; + int diag2 = row + col; + // ֦øСԽߡζԽϴڻʺ + if (!cols[col] && !diags1[diag1] && !diags2[diag2]) { + // ԣʺڸø + state[row][col] = "Q"; + cols[col] = diags1[diag1] = diags2[diag2] = true; + // һ + backtrack(row + 1, n, state, res, cols, diags1, diags2); + // ˣøӻָΪλ + state[row][col] = "#"; + cols[col] = diags1[diag1] = diags2[diag2] = false; + } + } +} + +/* n ʺ */ +vector>> nQueens(int n) { + // ʼ n*n С̣ 'Q' ʺ'#' λ + vector> state(n, vector(n, "#")); + vector cols(n, false); // ¼Ƿлʺ + vector diags1(2 * n - 1, false); // ¼ԽǷлʺ + vector diags2(2 * n - 1, false); // ¼ζԽǷлʺ + vector>> res; + + backtrack(0, n, state, res, cols, diags1, diags2); + + return res; +} + +/* Driver Code */ +int main() { + int n = 4; + vector>> res = nQueens(n); + + cout << "̳Ϊ " << n << endl; + cout << "ʺ÷ " << res.size() << " " << endl; + for (const vector> &state : res) { + cout << "--------------------" << endl; + for (const vector &row : state) { + printVector(row); + } + } + + return 0; +} diff --git a/chapter_backtracking/permutations_i.cpp b/chapter_backtracking/permutations_i.cpp new file mode 100644 index 0000000..da57810 --- /dev/null +++ b/chapter_backtracking/permutations_i.cpp @@ -0,0 +1,54 @@ +/** + * File: permutations_i.cpp + * Created Time: 2023-04-24 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* 㷨ȫ I */ +void backtrack(vector &state, const vector &choices, vector &selected, vector> &res) { + // ״̬ȵԪʱ¼ + if (state.size() == choices.size()) { + res.push_back(state); + return; + } + // ѡ + for (int i = 0; i < choices.size(); i++) { + int choice = choices[i]; + // ֦ظѡԪ + if (!selected[i]) { + // ԣѡ񣬸״̬ + selected[i] = true; + state.push_back(choice); + // һѡ + backtrack(state, choices, selected, res); + // ˣѡ񣬻ָ֮ǰ״̬ + selected[i] = false; + state.pop_back(); + } + } +} + +/* ȫ I */ +vector> permutationsI(vector nums) { + vector state; + vector selected(nums.size(), false); + vector> res; + backtrack(state, nums, selected, res); + return res; +} + +/* Driver Code */ +int main() { + vector nums = {1, 2, 3}; + + vector> res = permutationsI(nums); + + cout << " nums = "; + printVector(nums); + cout << " res = "; + printVectorMatrix(res); + + return 0; +} diff --git a/chapter_backtracking/permutations_ii.cpp b/chapter_backtracking/permutations_ii.cpp new file mode 100644 index 0000000..a113be4 --- /dev/null +++ b/chapter_backtracking/permutations_ii.cpp @@ -0,0 +1,56 @@ +/** + * File: permutations_ii.cpp + * Created Time: 2023-04-24 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* 㷨ȫ II */ +void backtrack(vector &state, const vector &choices, vector &selected, vector> &res) { + // ״̬ȵԪʱ¼ + if (state.size() == choices.size()) { + res.push_back(state); + return; + } + // ѡ + unordered_set duplicated; + for (int i = 0; i < choices.size(); i++) { + int choice = choices[i]; + // ֦ظѡԪ ظѡԪ + if (!selected[i] && duplicated.find(choice) == duplicated.end()) { + // ԣѡ񣬸״̬ + duplicated.emplace(choice); // ¼ѡԪֵ + selected[i] = true; + state.push_back(choice); + // һѡ + backtrack(state, choices, selected, res); + // ˣѡ񣬻ָ֮ǰ״̬ + selected[i] = false; + state.pop_back(); + } + } +} + +/* ȫ II */ +vector> permutationsII(vector nums) { + vector state; + vector selected(nums.size(), false); + vector> res; + backtrack(state, nums, selected, res); + return res; +} + +/* Driver Code */ +int main() { + vector nums = {1, 1, 2}; + + vector> res = permutationsII(nums); + + cout << " nums = "; + printVector(nums); + cout << " res = "; + printVectorMatrix(res); + + return 0; +} diff --git a/chapter_backtracking/preorder_traversal_i_compact.cpp b/chapter_backtracking/preorder_traversal_i_compact.cpp new file mode 100644 index 0000000..811ae38 --- /dev/null +++ b/chapter_backtracking/preorder_traversal_i_compact.cpp @@ -0,0 +1,39 @@ +/** + * File: preorder_traversal_i_compact.cpp + * Created Time: 2023-04-16 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +vector res; + +/* ǰһ */ +void preOrder(TreeNode *root) { + if (root == nullptr) { + return; + } + if (root->val == 7) { + // ¼ + res.push_back(root); + } + preOrder(root->left); + preOrder(root->right); +} + +/* Driver Code */ +int main() { + TreeNode *root = vectorToTree(vector{1, 7, 3, 4, 5, 6, 7}); + cout << "\nʼ" << endl; + printTree(root); + + // ǰ + preOrder(root); + + cout << "\nֵΪ 7 Ľڵ" << endl; + vector vals; + for (TreeNode *node : res) { + vals.push_back(node->val); + } + printVector(vals); +} diff --git a/chapter_backtracking/preorder_traversal_ii_compact.cpp b/chapter_backtracking/preorder_traversal_ii_compact.cpp new file mode 100644 index 0000000..5a549e9 --- /dev/null +++ b/chapter_backtracking/preorder_traversal_ii_compact.cpp @@ -0,0 +1,46 @@ +/** + * File: preorder_traversal_ii_compact.cpp + * Created Time: 2023-04-16 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +vector path; +vector> res; + +/* ǰ */ +void preOrder(TreeNode *root) { + if (root == nullptr) { + return; + } + // + path.push_back(root); + if (root->val == 7) { + // ¼ + res.push_back(path); + } + preOrder(root->left); + preOrder(root->right); + // + path.pop_back(); +} + +/* Driver Code */ +int main() { + TreeNode *root = vectorToTree(vector{1, 7, 3, 4, 5, 6, 7}); + cout << "\nʼ" << endl; + printTree(root); + + // ǰ + preOrder(root); + + cout << "\nиڵ㵽ڵ 7 ·" << endl; + for (vector &path : res) { + vector vals; + for (TreeNode *node : path) { + vals.push_back(node->val); + } + printVector(vals); + } +} diff --git a/chapter_backtracking/preorder_traversal_iii_compact.cpp b/chapter_backtracking/preorder_traversal_iii_compact.cpp new file mode 100644 index 0000000..f806e2d --- /dev/null +++ b/chapter_backtracking/preorder_traversal_iii_compact.cpp @@ -0,0 +1,47 @@ +/** + * File: preorder_traversal_iii_compact.cpp + * Created Time: 2023-04-16 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +vector path; +vector> res; + +/* ǰ */ +void preOrder(TreeNode *root) { + // ֦ + if (root == nullptr || root->val == 3) { + return; + } + // + path.push_back(root); + if (root->val == 7) { + // ¼ + res.push_back(path); + } + preOrder(root->left); + preOrder(root->right); + // + path.pop_back(); +} + +/* Driver Code */ +int main() { + TreeNode *root = vectorToTree(vector{1, 7, 3, 4, 5, 6, 7}); + cout << "\nʼ" << endl; + printTree(root); + + // ǰ + preOrder(root); + + cout << "\nиڵ㵽ڵ 7 ·Ҫ·вֵΪ 3 Ľڵ" << endl; + for (vector &path : res) { + vector vals; + for (TreeNode *node : path) { + vals.push_back(node->val); + } + printVector(vals); + } +} diff --git a/chapter_backtracking/preorder_traversal_iii_template.cpp b/chapter_backtracking/preorder_traversal_iii_template.cpp new file mode 100644 index 0000000..835d051 --- /dev/null +++ b/chapter_backtracking/preorder_traversal_iii_template.cpp @@ -0,0 +1,76 @@ +/** + * File: preorder_traversal_iii_template.cpp + * Created Time: 2023-04-16 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* жϵǰ״̬ǷΪ */ +bool isSolution(vector &state) { + return !state.empty() && state.back()->val == 7; +} + +/* ¼ */ +void recordSolution(vector &state, vector> &res) { + res.push_back(state); +} + +/* жڵǰ״̬£ѡǷϷ */ +bool isValid(vector &state, TreeNode *choice) { + return choice != nullptr && choice->val != 3; +} + +/* ״̬ */ +void makeChoice(vector &state, TreeNode *choice) { + state.push_back(choice); +} + +/* ָ״̬ */ +void undoChoice(vector &state, TreeNode *choice) { + state.pop_back(); +} + +/* 㷨 */ +void backtrack(vector &state, vector &choices, vector> &res) { + // ǷΪ + if (isSolution(state)) { + // ¼ + recordSolution(state, res); + } + // ѡ + for (TreeNode *choice : choices) { + // ֦ѡǷϷ + if (isValid(state, choice)) { + // ԣѡ񣬸״̬ + makeChoice(state, choice); + // һѡ + vector nextChoices{choice->left, choice->right}; + backtrack(state, nextChoices, res); + // ˣѡ񣬻ָ֮ǰ״̬ + undoChoice(state, choice); + } + } +} + +/* Driver Code */ +int main() { + TreeNode *root = vectorToTree(vector{1, 7, 3, 4, 5, 6, 7}); + cout << "\nʼ" << endl; + printTree(root); + + // 㷨 + vector state; + vector choices = {root}; + vector> res; + backtrack(state, choices, res); + + cout << "\nиڵ㵽ڵ 7 ·Ҫ·вֵΪ 3 Ľڵ" << endl; + for (vector &path : res) { + vector vals; + for (TreeNode *node : path) { + vals.push_back(node->val); + } + printVector(vals); + } +} diff --git a/chapter_backtracking/subset_sum_i.cpp b/chapter_backtracking/subset_sum_i.cpp new file mode 100644 index 0000000..b9998d2 --- /dev/null +++ b/chapter_backtracking/subset_sum_i.cpp @@ -0,0 +1,57 @@ +/** + * File: subset_sum_i.cpp + * Created Time: 2023-06-21 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* 㷨Ӽ I */ +void backtrack(vector &state, int target, vector &choices, int start, vector> &res) { + // Ӽ͵ target ʱ¼ + if (target == 0) { + res.push_back(state); + return; + } + // ѡ + // ֦ start ʼظӼ + for (int i = start; i < choices.size(); i++) { + // ֦һӼͳ target ֱӽѭ + // Ϊ򣬺ԪظӼһ target + if (target - choices[i] < 0) { + break; + } + // ԣѡ񣬸 target, start + state.push_back(choices[i]); + // һѡ + backtrack(state, target - choices[i], choices, i, res); + // ˣѡ񣬻ָ֮ǰ״̬ + state.pop_back(); + } +} + +/* Ӽ I */ +vector> subsetSumI(vector &nums, int target) { + vector state; // ״̬Ӽ + sort(nums.begin(), nums.end()); // nums + int start = 0; // ʼ + vector> res; // бӼб + backtrack(state, target, nums, start, res); + return res; +} + +/* Driver Code */ +int main() { + vector nums = {3, 4, 5}; + int target = 9; + + vector> res = subsetSumI(nums, target); + + cout << " nums = "; + printVector(nums); + cout << "target = " << target << endl; + cout << "к͵ " << target << " Ӽ res = " << endl; + printVectorMatrix(res); + + return 0; +} diff --git a/chapter_backtracking/subset_sum_i_naive.cpp b/chapter_backtracking/subset_sum_i_naive.cpp new file mode 100644 index 0000000..0947a9b --- /dev/null +++ b/chapter_backtracking/subset_sum_i_naive.cpp @@ -0,0 +1,54 @@ +/** + * File: subset_sum_i_naive.cpp + * Created Time: 2023-06-21 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* 㷨Ӽ I */ +void backtrack(vector &state, int target, int total, vector &choices, vector> &res) { + // Ӽ͵ target ʱ¼ + if (total == target) { + res.push_back(state); + return; + } + // ѡ + for (size_t i = 0; i < choices.size(); i++) { + // ֦Ӽͳ target ѡ + if (total + choices[i] > target) { + continue; + } + // ԣѡ񣬸Ԫغ total + state.push_back(choices[i]); + // һѡ + backtrack(state, target, total + choices[i], choices, res); + // ˣѡ񣬻ָ֮ǰ״̬ + state.pop_back(); + } +} + +/* Ӽ IظӼ */ +vector> subsetSumINaive(vector &nums, int target) { + vector state; // ״̬Ӽ + int total = 0; // Ӽ + vector> res; // бӼб + backtrack(state, target, total, nums, res); + return res; +} + +/* Driver Code */ +int main() { + vector nums = {3, 4, 5}; + int target = 9; + + vector> res = subsetSumINaive(nums, target); + + cout << " nums = "; + printVector(nums); + cout << "target = " << target << endl; + cout << "к͵ " << target << " Ӽ res = " << endl; + printVectorMatrix(res); + + return 0; +} diff --git a/chapter_backtracking/subset_sum_ii.cpp b/chapter_backtracking/subset_sum_ii.cpp new file mode 100644 index 0000000..9c277aa --- /dev/null +++ b/chapter_backtracking/subset_sum_ii.cpp @@ -0,0 +1,62 @@ +/** + * File: subset_sum_ii.cpp + * Created Time: 2023-06-21 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* 㷨Ӽ II */ +void backtrack(vector &state, int target, vector &choices, int start, vector> &res) { + // Ӽ͵ target ʱ¼ + if (target == 0) { + res.push_back(state); + return; + } + // ѡ + // ֦ start ʼظӼ + // ֦ start ʼظѡͬһԪ + for (int i = start; i < choices.size(); i++) { + // ֦һӼͳ target ֱӽѭ + // Ϊ򣬺ԪظӼһ target + if (target - choices[i] < 0) { + break; + } + // ֦ģԪԪȣ˵֧ظֱ + if (i > start && choices[i] == choices[i - 1]) { + continue; + } + // ԣѡ񣬸 target, start + state.push_back(choices[i]); + // һѡ + backtrack(state, target - choices[i], choices, i + 1, res); + // ˣѡ񣬻ָ֮ǰ״̬ + state.pop_back(); + } +} + +/* Ӽ II */ +vector> subsetSumII(vector &nums, int target) { + vector state; // ״̬Ӽ + sort(nums.begin(), nums.end()); // nums + int start = 0; // ʼ + vector> res; // бӼб + backtrack(state, target, nums, start, res); + return res; +} + +/* Driver Code */ +int main() { + vector nums = {4, 4, 5}; + int target = 9; + + vector> res = subsetSumII(nums, target); + + cout << " nums = "; + printVector(nums); + cout << "target = " << target << endl; + cout << "к͵ " << target << " Ӽ res = " << endl; + printVectorMatrix(res); + + return 0; +} diff --git a/chapter_computational_complexity/CMakeLists.txt b/chapter_computational_complexity/CMakeLists.txt new file mode 100644 index 0000000..ea2845b --- /dev/null +++ b/chapter_computational_complexity/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(iteration iteration.cpp) +add_executable(recursion recursion.cpp) +add_executable(space_complexity space_complexity.cpp) +add_executable(time_complexity time_complexity.cpp) +add_executable(worst_best_time_complexity worst_best_time_complexity.cpp) \ No newline at end of file diff --git a/chapter_computational_complexity/iteration.cpp b/chapter_computational_complexity/iteration.cpp new file mode 100644 index 0000000..cbefe8d --- /dev/null +++ b/chapter_computational_complexity/iteration.cpp @@ -0,0 +1,76 @@ +/** + * File: iteration.cpp + * Created Time: 2023-08-24 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* for ѭ */ +int forLoop(int n) { + int res = 0; + // ѭ 1, 2, ..., n-1, n + for (int i = 1; i <= n; ++i) { + res += i; + } + return res; +} + +/* while ѭ */ +int whileLoop(int n) { + int res = 0; + int i = 1; // ʼ + // ѭ 1, 2, ..., n-1, n + while (i <= n) { + res += i; + i++; // + } + return res; +} + +/* while ѭθ£ */ +int whileLoopII(int n) { + int res = 0; + int i = 1; // ʼ + // ѭ 1, 4, 10, ... + while (i <= n) { + res += i; + // + i++; + i *= 2; + } + return res; +} + +/* ˫ for ѭ */ +string nestedForLoop(int n) { + ostringstream res; + // ѭ i = 1, 2, ..., n-1, n + for (int i = 1; i <= n; ++i) { + // ѭ j = 1, 2, ..., n-1, n + for (int j = 1; j <= n; ++j) { + res << "(" << i << ", " << j << "), "; + } + } + return res.str(); +} + +/* Driver Code */ +int main() { + int n = 5; + int res; + + res = forLoop(n); + cout << "\nfor ѭͽ res = " << res << endl; + + res = whileLoop(n); + cout << "\nwhile ѭͽ res = " << res << endl; + + res = whileLoopII(n); + cout << "\nwhile ѭθ£ͽ res = " << res << endl; + + string resStr = nestedForLoop(n); + cout << "\n˫ for ѭı " << resStr << endl; + + return 0; +} diff --git a/chapter_computational_complexity/recursion.cpp b/chapter_computational_complexity/recursion.cpp new file mode 100644 index 0000000..60d2eb8 --- /dev/null +++ b/chapter_computational_complexity/recursion.cpp @@ -0,0 +1,78 @@ +/** + * File: recursion.cpp + * Created Time: 2023-08-24 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ݹ */ +int recur(int n) { + // ֹ + if (n == 1) + return 1; + // ݣݹ + int res = recur(n - 1); + // 飺ؽ + return n + res; +} + +/* ʹõģݹ */ +int forLoopRecur(int n) { + // ʹһʽջģϵͳջ + stack stack; + int res = 0; + // ݣݹ + for (int i = n; i > 0; i--) { + // ͨջģ⡰ݡ + stack.push(i); + } + // 飺ؽ + while (!stack.empty()) { + // ͨջģ⡰顱 + res += stack.top(); + stack.pop(); + } + // res = 1+2+3+...+n + return res; +} + +/* βݹ */ +int tailRecur(int n, int res) { + // ֹ + if (n == 0) + return res; + // βݹ + return tailRecur(n - 1, res + n); +} + +/* 쳲Уݹ */ +int fib(int n) { + // ֹ f(1) = 0, f(2) = 1 + if (n == 1 || n == 2) + return n - 1; + // ݹ f(n) = f(n-1) + f(n-2) + int res = fib(n - 1) + fib(n - 2); + // ؽ f(n) + return res; +} + +/* Driver Code */ +int main() { + int n = 5; + int res; + + res = recur(n); + cout << "\nݹ麯ͽ res = " << res << endl; + + res = forLoopRecur(n); + cout << "\nʹõģݹͽ res = " << res << endl; + + res = tailRecur(n, 0); + cout << "\nβݹ麯ͽ res = " << res << endl; + + res = fib(n); + cout << "\n쳲еĵ " << n << " Ϊ " << res << endl; + + return 0; +} diff --git a/chapter_computational_complexity/space_complexity.cpp b/chapter_computational_complexity/space_complexity.cpp new file mode 100644 index 0000000..6f9944f --- /dev/null +++ b/chapter_computational_complexity/space_complexity.cpp @@ -0,0 +1,107 @@ +/** + * File: space_complexity.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +int func() { + // ִijЩ + return 0; +} + +/* */ +void constant(int n) { + // ռ O(1) ռ + const int a = 0; + int b = 0; + vector nums(10000); + ListNode node(0); + // ѭеıռ O(1) ռ + for (int i = 0; i < n; i++) { + int c = 0; + } + // ѭеĺռ O(1) ռ + for (int i = 0; i < n; i++) { + func(); + } +} + +/* Խ */ +void linear(int n) { + // Ϊ n ռ O(n) ռ + vector nums(n); + // Ϊ n бռ O(n) ռ + vector nodes; + for (int i = 0; i < n; i++) { + nodes.push_back(ListNode(i)); + } + // Ϊ n Ĺϣռ O(n) ռ + unordered_map map; + for (int i = 0; i < n; i++) { + map[i] = to_string(i); + } +} + +/* Խףݹʵ֣ */ +void linearRecur(int n) { + cout << "ݹ n = " << n << endl; + if (n == 1) + return; + linearRecur(n - 1); +} + +/* ƽ */ +void quadratic(int n) { + // άбռ O(n^2) ռ + vector> numMatrix; + for (int i = 0; i < n; i++) { + vector tmp; + for (int j = 0; j < n; j++) { + tmp.push_back(0); + } + numMatrix.push_back(tmp); + } +} + +/* ƽףݹʵ֣ */ +int quadraticRecur(int n) { + if (n <= 0) + return 0; + vector nums(n); + cout << "ݹ n = " << n << " е nums = " << nums.size() << endl; + return quadraticRecur(n - 1); +} + +/* ָף */ +TreeNode *buildTree(int n) { + if (n == 0) + return nullptr; + TreeNode *root = new TreeNode(0); + root->left = buildTree(n - 1); + root->right = buildTree(n - 1); + return root; +} + +/* Driver Code */ +int main() { + int n = 5; + // + constant(n); + // Խ + linear(n); + linearRecur(n); + // ƽ + quadratic(n); + quadraticRecur(n); + // ָ + TreeNode *root = buildTree(n); + printTree(root); + + // ͷڴ + freeMemoryTree(root); + + return 0; +} diff --git a/chapter_computational_complexity/time_complexity.cpp b/chapter_computational_complexity/time_complexity.cpp new file mode 100644 index 0000000..2ba6ccc --- /dev/null +++ b/chapter_computational_complexity/time_complexity.cpp @@ -0,0 +1,168 @@ +/** + * File: time_complexity.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +int constant(int n) { + int count = 0; + int size = 100000; + for (int i = 0; i < size; i++) + count++; + return count; +} + +/* Խ */ +int linear(int n) { + int count = 0; + for (int i = 0; i < n; i++) + count++; + return count; +} + +/* Խף飩 */ +int arrayTraversal(vector &nums) { + int count = 0; + // ѭ鳤ȳ + for (int num : nums) { + count++; + } + return count; +} + +/* ƽ */ +int quadratic(int n) { + int count = 0; + // ѭ鳤ȳƽϵ + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + count++; + } + } + return count; +} + +/* ƽףð */ +int bubbleSort(vector &nums) { + int count = 0; // + // ѭδΪ [0, i] + for (int i = nums.size() - 1; i > 0; i--) { + // ѭδ [0, i] еԪؽҶ + for (int j = 0; j < i; j++) { + if (nums[j] > nums[j + 1]) { + // nums[j] nums[j + 1] + int tmp = nums[j]; + nums[j] = nums[j + 1]; + nums[j + 1] = tmp; + count += 3; // Ԫؽ 3 Ԫ + } + } + } + return count; +} + +/* ָףѭʵ֣ */ +int exponential(int n) { + int count = 0, base = 1; + // ϸÿһΪγ 1, 2, 4, 8, ..., 2^(n-1) + for (int i = 0; i < n; i++) { + for (int j = 0; j < base; j++) { + count++; + } + base *= 2; + } + // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 + return count; +} + +/* ָףݹʵ֣ */ +int expRecur(int n) { + if (n == 1) + return 1; + return expRecur(n - 1) + expRecur(n - 1) + 1; +} + +/* ףѭʵ֣ */ +int logarithmic(float n) { + int count = 0; + while (n > 1) { + n = n / 2; + count++; + } + return count; +} + +/* ףݹʵ֣ */ +int logRecur(float n) { + if (n <= 1) + return 0; + return logRecur(n / 2) + 1; +} + +/* Զ */ +int linearLogRecur(float n) { + if (n <= 1) + return 1; + int count = linearLogRecur(n / 2) + linearLogRecur(n / 2); + for (int i = 0; i < n; i++) { + count++; + } + return count; +} + +/* ׳˽ףݹʵ֣ */ +int factorialRecur(int n) { + if (n == 0) + return 1; + int count = 0; + // 1 ѳ n + for (int i = 0; i < n; i++) { + count += factorialRecur(n - 1); + } + return count; +} + +/* Driver Code */ +int main() { + // ޸ n Уһ¸ָӶȵIJ仯 + int n = 8; + cout << "ݴС n = " << n << endl; + + int count = constant(n); + cout << "׵IJ = " << count << endl; + + count = linear(n); + cout << "Խ׵IJ = " << count << endl; + vector arr(n); + count = arrayTraversal(arr); + cout << "Խף飩IJ = " << count << endl; + + count = quadratic(n); + cout << "ƽ׵IJ = " << count << endl; + vector nums(n); + for (int i = 0; i < n; i++) + nums[i] = n - i; // [n,n-1,...,2,1] + count = bubbleSort(nums); + cout << "ƽףð򣩵IJ = " << count << endl; + + count = exponential(n); + cout << "ָףѭʵ֣IJ = " << count << endl; + count = expRecur(n); + cout << "ָףݹʵ֣IJ = " << count << endl; + + count = logarithmic((float)n); + cout << "ףѭʵ֣IJ = " << count << endl; + count = logRecur((float)n); + cout << "ףݹʵ֣IJ = " << count << endl; + + count = linearLogRecur((float)n); + cout << "Զףݹʵ֣IJ = " << count << endl; + + count = factorialRecur(n); + cout << "׳˽ףݹʵ֣IJ = " << count << endl; + + return 0; +} diff --git a/chapter_computational_complexity/worst_best_time_complexity.cpp b/chapter_computational_complexity/worst_best_time_complexity.cpp new file mode 100644 index 0000000..5e8843f --- /dev/null +++ b/chapter_computational_complexity/worst_best_time_complexity.cpp @@ -0,0 +1,45 @@ +/** + * File: worst_best_time_complexity.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* һ飬ԪΪ { 1, 2, ..., n }˳򱻴 */ +vector randomNumbers(int n) { + vector nums(n); + // nums = { 1, 2, 3, ..., n } + for (int i = 0; i < n; i++) { + nums[i] = i + 1; + } + // ʹϵͳʱ + unsigned seed = chrono::system_clock::now().time_since_epoch().count(); + // Ԫ + shuffle(nums.begin(), nums.end(), default_random_engine(seed)); + return nums; +} + +/* nums 1 */ +int findOne(vector &nums) { + for (int i = 0; i < nums.size(); i++) { + // Ԫ 1 ͷʱﵽʱ临Ӷ O(1) + // Ԫ 1 βʱﵽʱ临Ӷ O(n) + if (nums[i] == 1) + return i; + } + return -1; +} + +/* Driver Code */ +int main() { + for (int i = 0; i < 1000; i++) { + int n = 100; + vector nums = randomNumbers(n); + int index = findOne(nums); + cout << "\n [ 1, 2, ..., n ] Һ = "; + printVector(nums); + cout << " 1 Ϊ " << index << endl; + } + return 0; +} diff --git a/chapter_divide_and_conquer/CMakeLists.txt b/chapter_divide_and_conquer/CMakeLists.txt new file mode 100644 index 0000000..38dfff7 --- /dev/null +++ b/chapter_divide_and_conquer/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(binary_search_recur binary_search_recur.cpp) +add_executable(build_tree build_tree.cpp) +add_executable(hanota hanota.cpp) \ No newline at end of file diff --git a/chapter_divide_and_conquer/binary_search_recur.cpp b/chapter_divide_and_conquer/binary_search_recur.cpp new file mode 100644 index 0000000..d72de52 --- /dev/null +++ b/chapter_divide_and_conquer/binary_search_recur.cpp @@ -0,0 +1,46 @@ +/** + * File: binary_search_recur.cpp + * Created Time: 2023-07-17 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ֲң f(i, j) */ +int dfs(vector &nums, int target, int i, int j) { + // ΪգĿԪأ򷵻 -1 + if (i > j) { + return -1; + } + // е m + int m = (i + j) / 2; + if (nums[m] < target) { + // ݹ f(m+1, j) + return dfs(nums, target, m + 1, j); + } else if (nums[m] > target) { + // ݹ f(i, m-1) + return dfs(nums, target, i, m - 1); + } else { + // ҵĿԪأ + return m; + } +} + +/* ֲ */ +int binarySearch(vector &nums, int target) { + int n = nums.size(); + // f(0, n-1) + return dfs(nums, target, 0, n - 1); +} + +/* Driver Code */ +int main() { + int target = 6; + vector nums = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35}; + + // ֲң˫䣩 + int index = binarySearch(nums, target); + cout << "ĿԪ 6 = " << index << endl; + + return 0; +} \ No newline at end of file diff --git a/chapter_divide_and_conquer/build_tree.cpp b/chapter_divide_and_conquer/build_tree.cpp new file mode 100644 index 0000000..a677e72 --- /dev/null +++ b/chapter_divide_and_conquer/build_tree.cpp @@ -0,0 +1,51 @@ +/** + * File: build_tree.cpp + * Created Time: 2023-07-17 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +TreeNode *dfs(vector &preorder, unordered_map &inorderMap, int i, int l, int r) { + // Ϊʱֹ + if (r - l < 0) + return NULL; + // ʼڵ + TreeNode *root = new TreeNode(preorder[i]); + // ѯ m Ӷ + int m = inorderMap[preorder[i]]; + // ⣺ + root->left = dfs(preorder, inorderMap, i + 1, l, m - 1); + // ⣺ + root->right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r); + // ظڵ + return root; +} + +/* */ +TreeNode *buildTree(vector &preorder, vector &inorder) { + // ʼϣ洢 inorder Ԫصӳ + unordered_map inorderMap; + for (int i = 0; i < inorder.size(); i++) { + inorderMap[inorder[i]] = i; + } + TreeNode *root = dfs(preorder, inorderMap, 0, 0, inorder.size() - 1); + return root; +} + +/* Driver Code */ +int main() { + vector preorder = {3, 9, 2, 1, 7}; + vector inorder = {9, 3, 1, 2, 7}; + cout << "ǰ = "; + printVector(preorder); + cout << " = "; + printVector(inorder); + + TreeNode *root = buildTree(preorder, inorder); + cout << "ĶΪ\n"; + printTree(root); + + return 0; +} diff --git a/chapter_divide_and_conquer/hanota.cpp b/chapter_divide_and_conquer/hanota.cpp new file mode 100644 index 0000000..79313b3 --- /dev/null +++ b/chapter_divide_and_conquer/hanota.cpp @@ -0,0 +1,66 @@ +/** + * File: hanota.cpp + * Created Time: 2023-07-17 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ƶһԲ */ +void move(vector &src, vector &tar) { + // src óһԲ + int pan = src.back(); + src.pop_back(); + // Բ̷ tar + tar.push_back(pan); +} + +/* ⺺ŵ f(i) */ +void dfs(int i, vector &src, vector &buf, vector &tar) { + // src ֻʣһԲֱ̣ӽƵ tar + if (i == 1) { + move(src, tar); + return; + } + // f(i-1) src i-1 Բ̽ tar Ƶ buf + dfs(i - 1, src, tar, buf); + // f(1) src ʣһԲƵ tar + move(src, tar); + // f(i-1) buf i-1 Բ̽ src Ƶ tar + dfs(i - 1, buf, src, tar); +} + +/* ⺺ŵ */ +void solveHanota(vector &A, vector &B, vector &C) { + int n = A.size(); + // A n Բ̽ B Ƶ C + dfs(n, A, B, C); +} + +/* Driver Code */ +int main() { + // бβӶ + vector A = {5, 4, 3, 2, 1}; + vector B = {}; + vector C = {}; + + cout << "ʼ״̬£\n"; + cout << "A ="; + printVector(A); + cout << "B ="; + printVector(B); + cout << "C ="; + printVector(C); + + solveHanota(A, B, C); + + cout << "Բƶɺ\n"; + cout << "A ="; + printVector(A); + cout << "B ="; + printVector(B); + cout << "C ="; + printVector(C); + + return 0; +} diff --git a/chapter_dynamic_programming/CMakeLists.txt b/chapter_dynamic_programming/CMakeLists.txt new file mode 100644 index 0000000..ed18545 --- /dev/null +++ b/chapter_dynamic_programming/CMakeLists.txt @@ -0,0 +1,10 @@ +add_executable(climbing_stairs_backtrack climbing_stairs_backtrack.cpp) +add_executable(climbing_stairs_dfs climbing_stairs_dfs.cpp) +add_executable(climbing_stairs_dfs_mem climbing_stairs_dfs_mem.cpp) +add_executable(climbing_stairs_dp climbing_stairs_dp.cpp) +add_executable(min_cost_climbing_stairs_dp min_cost_climbing_stairs_dp.cpp) +add_executable(min_path_sum min_path_sum.cpp) +add_executable(unbounded_knapsack unbounded_knapsack.cpp) +add_executable(coin_change coin_change.cpp) +add_executable(coin_change_ii coin_change_ii.cpp) +add_executable(edit_distance edit_distance.cpp) \ No newline at end of file diff --git a/chapter_dynamic_programming/climbing_stairs_backtrack.cpp b/chapter_dynamic_programming/climbing_stairs_backtrack.cpp new file mode 100644 index 0000000..dbe405f --- /dev/null +++ b/chapter_dynamic_programming/climbing_stairs_backtrack.cpp @@ -0,0 +1,43 @@ + +/** + * File: climbing_stairs_backtrack.cpp + * Created Time: 2023-06-30 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +void backtrack(vector &choices, int state, int n, vector &res) { + // n ʱ 1 + if (state == n) + res[0]++; + // ѡ + for (auto &choice : choices) { + // ֦Խ n + if (state + choice > n) + continue; + // ԣѡ񣬸״̬ + backtrack(choices, state + choice, n, res); + // + } +} + +/* ¥ݣ */ +int climbingStairsBacktrack(int n) { + vector choices = {1, 2}; // ѡ 1 ׻ 2 + int state = 0; // ӵ 0 ׿ʼ + vector res = {0}; // ʹ res[0] ¼ + backtrack(choices, state, n, res); + return res[0]; +} + +/* Driver Code */ +int main() { + int n = 9; + + int res = climbingStairsBacktrack(n); + cout << " " << n << " ¥ݹ " << res << " ַ" << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/climbing_stairs_constraint_dp.cpp b/chapter_dynamic_programming/climbing_stairs_constraint_dp.cpp new file mode 100644 index 0000000..c5b5db1 --- /dev/null +++ b/chapter_dynamic_programming/climbing_stairs_constraint_dp.cpp @@ -0,0 +1,37 @@ +/** + * File: climbing_stairs_constraint_dp.cpp + * Created Time: 2023-07-01 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Լ¥ݣ̬滮 */ +int climbingStairsConstraintDP(int n) { + if (n == 1 || n == 2) { + return 1; + } + // ʼ dp ڴ洢Ľ + vector> dp(n + 1, vector(3, 0)); + // ʼ״̬ԤСĽ + dp[1][1] = 1; + dp[1][2] = 0; + dp[2][1] = 0; + dp[2][2] = 1; + // ״̬תƣӽСϴ + for (int i = 3; i <= n; i++) { + dp[i][1] = dp[i - 1][2]; + dp[i][2] = dp[i - 2][1] + dp[i - 2][2]; + } + return dp[n][1] + dp[n][2]; +} + +/* Driver Code */ +int main() { + int n = 9; + + int res = climbingStairsConstraintDP(n); + cout << " " << n << " ¥ݹ " << res << " ַ" << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/climbing_stairs_dfs.cpp b/chapter_dynamic_programming/climbing_stairs_dfs.cpp new file mode 100644 index 0000000..73b5e80 --- /dev/null +++ b/chapter_dynamic_programming/climbing_stairs_dfs.cpp @@ -0,0 +1,32 @@ +/** + * File: climbing_stairs_dfs.cpp + * Created Time: 2023-06-30 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +int dfs(int i) { + // ֪ dp[1] dp[2] ֮ + if (i == 1 || i == 2) + return i; + // dp[i] = dp[i-1] + dp[i-2] + int count = dfs(i - 1) + dfs(i - 2); + return count; +} + +/* ¥ݣ */ +int climbingStairsDFS(int n) { + return dfs(n); +} + +/* Driver Code */ +int main() { + int n = 9; + + int res = climbingStairsDFS(n); + cout << " " << n << " ¥ݹ " << res << " ַ" << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/climbing_stairs_dfs_mem.cpp b/chapter_dynamic_programming/climbing_stairs_dfs_mem.cpp new file mode 100644 index 0000000..a8cc1ea --- /dev/null +++ b/chapter_dynamic_programming/climbing_stairs_dfs_mem.cpp @@ -0,0 +1,39 @@ +/** + * File: climbing_stairs_dfs_mem.cpp + * Created Time: 2023-06-30 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* 仯 */ +int dfs(int i, vector &mem) { + // ֪ dp[1] dp[2] ֮ + if (i == 1 || i == 2) + return i; + // ڼ¼ dp[i] ֱӷ֮ + if (mem[i] != -1) + return mem[i]; + // dp[i] = dp[i-1] + dp[i-2] + int count = dfs(i - 1, mem) + dfs(i - 2, mem); + // ¼ dp[i] + mem[i] = count; + return count; +} + +/* ¥ݣ仯 */ +int climbingStairsDFSMem(int n) { + // mem[i] ¼ i ׵ķ-1 ޼¼ + vector mem(n + 1, -1); + return dfs(n, mem); +} + +/* Driver Code */ +int main() { + int n = 9; + + int res = climbingStairsDFSMem(n); + cout << " " << n << " ¥ݹ " << res << " ַ" << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/climbing_stairs_dp.cpp b/chapter_dynamic_programming/climbing_stairs_dp.cpp new file mode 100644 index 0000000..5eb5ddf --- /dev/null +++ b/chapter_dynamic_programming/climbing_stairs_dp.cpp @@ -0,0 +1,49 @@ +/** + * File: climbing_stairs_dp.cpp + * Created Time: 2023-06-30 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ¥ݣ̬滮 */ +int climbingStairsDP(int n) { + if (n == 1 || n == 2) + return n; + // ʼ dp ڴ洢Ľ + vector dp(n + 1); + // ʼ״̬ԤСĽ + dp[1] = 1; + dp[2] = 2; + // ״̬תƣӽСϴ + for (int i = 3; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n]; +} + +/* ¥ݣռŻĶ̬滮 */ +int climbingStairsDPComp(int n) { + if (n == 1 || n == 2) + return n; + int a = 1, b = 2; + for (int i = 3; i <= n; i++) { + int tmp = b; + b = a + b; + a = tmp; + } + return b; +} + +/* Driver Code */ +int main() { + int n = 9; + + int res = climbingStairsDP(n); + cout << " " << n << " ¥ݹ " << res << " ַ" << endl; + + res = climbingStairsDPComp(n); + cout << " " << n << " ¥ݹ " << res << " ַ" << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/coin_change.cpp b/chapter_dynamic_programming/coin_change.cpp new file mode 100644 index 0000000..2daa2ac --- /dev/null +++ b/chapter_dynamic_programming/coin_change.cpp @@ -0,0 +1,70 @@ +/** + * File: coin_change.cpp + * Created Time: 2023-07-11 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Ǯһ̬滮 */ +int coinChangeDP(vector &coins, int amt) { + int n = coins.size(); + int MAX = amt + 1; + // ʼ dp + vector> dp(n + 1, vector(amt + 1, 0)); + // ״̬תƣ + for (int a = 1; a <= amt; a++) { + dp[0][a] = MAX; + } + // ״̬תƣк + for (int i = 1; i <= n; i++) { + for (int a = 1; a <= amt; a++) { + if (coins[i - 1] > a) { + // ĿѡӲ i + dp[i][a] = dp[i - 1][a]; + } else { + // ѡѡӲ i ַĽСֵ + dp[i][a] = min(dp[i - 1][a], dp[i][a - coins[i - 1]] + 1); + } + } + } + return dp[n][amt] != MAX ? dp[n][amt] : -1; +} + +/* ǮһռŻĶ̬滮 */ +int coinChangeDPComp(vector &coins, int amt) { + int n = coins.size(); + int MAX = amt + 1; + // ʼ dp + vector dp(amt + 1, MAX); + dp[0] = 0; + // ״̬ת + for (int i = 1; i <= n; i++) { + for (int a = 1; a <= amt; a++) { + if (coins[i - 1] > a) { + // ĿѡӲ i + dp[a] = dp[a]; + } else { + // ѡѡӲ i ַĽСֵ + dp[a] = min(dp[a], dp[a - coins[i - 1]] + 1); + } + } + } + return dp[amt] != MAX ? dp[amt] : -1; +} + +/* Driver code */ +int main() { + vector coins = {1, 2, 5}; + int amt = 4; + + // ̬滮 + int res = coinChangeDP(coins, amt); + cout << "յĿӲΪ " << res << endl; + + // ռŻĶ̬滮 + res = coinChangeDPComp(coins, amt); + cout << "յĿӲΪ " << res << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/coin_change_ii.cpp b/chapter_dynamic_programming/coin_change_ii.cpp new file mode 100644 index 0000000..302eb7e --- /dev/null +++ b/chapter_dynamic_programming/coin_change_ii.cpp @@ -0,0 +1,68 @@ +/** + * File: coin_change_ii.cpp + * Created Time: 2023-07-11 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Ǯһ II̬滮 */ +int coinChangeIIDP(vector &coins, int amt) { + int n = coins.size(); + // ʼ dp + vector> dp(n + 1, vector(amt + 1, 0)); + // ʼ + for (int i = 0; i <= n; i++) { + dp[i][0] = 1; + } + // ״̬ת + for (int i = 1; i <= n; i++) { + for (int a = 1; a <= amt; a++) { + if (coins[i - 1] > a) { + // ĿѡӲ i + dp[i][a] = dp[i - 1][a]; + } else { + // ѡѡӲ i ַ֮ + dp[i][a] = dp[i - 1][a] + dp[i][a - coins[i - 1]]; + } + } + } + return dp[n][amt]; +} + +/* Ǯһ IIռŻĶ̬滮 */ +int coinChangeIIDPComp(vector &coins, int amt) { + int n = coins.size(); + // ʼ dp + vector dp(amt + 1, 0); + dp[0] = 1; + // ״̬ת + for (int i = 1; i <= n; i++) { + for (int a = 1; a <= amt; a++) { + if (coins[i - 1] > a) { + // ĿѡӲ i + dp[a] = dp[a]; + } else { + // ѡѡӲ i ַ֮ + dp[a] = dp[a] + dp[a - coins[i - 1]]; + } + } + } + return dp[amt]; +} + +/* Driver code */ +int main() { + vector coins = {1, 2, 5}; + int amt = 5; + + // ̬滮 + int res = coinChangeIIDP(coins, amt); + cout << "ճĿӲΪ " << res << endl; + + // ռŻĶ̬滮 + res = coinChangeIIDPComp(coins, amt); + cout << "ճĿӲΪ " << res << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/edit_distance.cpp b/chapter_dynamic_programming/edit_distance.cpp new file mode 100644 index 0000000..6257189 --- /dev/null +++ b/chapter_dynamic_programming/edit_distance.cpp @@ -0,0 +1,136 @@ +/** + * File: edit_distance.cpp + * Created Time: 2023-07-13 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ༭룺 */ +int editDistanceDFS(string s, string t, int i, int j) { + // s t Ϊգ򷵻 0 + if (i == 0 && j == 0) + return 0; + // s Ϊգ򷵻 t + if (i == 0) + return j; + // t Ϊգ򷵻 s + if (j == 0) + return i; + // ַȣֱַ + if (s[i - 1] == t[j - 1]) + return editDistanceDFS(s, t, i - 1, j - 1); + // ٱ༭ = 롢ɾ滻ֲٱ༭ + 1 + int insert = editDistanceDFS(s, t, i, j - 1); + int del = editDistanceDFS(s, t, i - 1, j); + int replace = editDistanceDFS(s, t, i - 1, j - 1); + // ٱ༭ + return min(min(insert, del), replace) + 1; +} + +/* ༭룺仯 */ +int editDistanceDFSMem(string s, string t, vector> &mem, int i, int j) { + // s t Ϊգ򷵻 0 + if (i == 0 && j == 0) + return 0; + // s Ϊգ򷵻 t + if (i == 0) + return j; + // t Ϊգ򷵻 s + if (j == 0) + return i; + // м¼ֱӷ֮ + if (mem[i][j] != -1) + return mem[i][j]; + // ַȣֱַ + if (s[i - 1] == t[j - 1]) + return editDistanceDFSMem(s, t, mem, i - 1, j - 1); + // ٱ༭ = 롢ɾ滻ֲٱ༭ + 1 + int insert = editDistanceDFSMem(s, t, mem, i, j - 1); + int del = editDistanceDFSMem(s, t, mem, i - 1, j); + int replace = editDistanceDFSMem(s, t, mem, i - 1, j - 1); + // ¼ٱ༭ + mem[i][j] = min(min(insert, del), replace) + 1; + return mem[i][j]; +} + +/* ༭룺̬滮 */ +int editDistanceDP(string s, string t) { + int n = s.length(), m = t.length(); + vector> dp(n + 1, vector(m + 1, 0)); + // ״̬תƣ + for (int i = 1; i <= n; i++) { + dp[i][0] = i; + } + for (int j = 1; j <= m; j++) { + dp[0][j] = j; + } + // ״̬תƣк + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= m; j++) { + if (s[i - 1] == t[j - 1]) { + // ַȣֱַ + dp[i][j] = dp[i - 1][j - 1]; + } else { + // ٱ༭ = 롢ɾ滻ֲٱ༭ + 1 + dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1; + } + } + } + return dp[n][m]; +} + +/* ༭룺ռŻĶ̬滮 */ +int editDistanceDPComp(string s, string t) { + int n = s.length(), m = t.length(); + vector dp(m + 1, 0); + // ״̬תƣ + for (int j = 1; j <= m; j++) { + dp[j] = j; + } + // ״̬תƣ + for (int i = 1; i <= n; i++) { + // ״̬תƣ + int leftup = dp[0]; // ݴ dp[i-1, j-1] + dp[0] = i; + // ״̬תƣ + for (int j = 1; j <= m; j++) { + int temp = dp[j]; + if (s[i - 1] == t[j - 1]) { + // ַȣֱַ + dp[j] = leftup; + } else { + // ٱ༭ = 롢ɾ滻ֲٱ༭ + 1 + dp[j] = min(min(dp[j - 1], dp[j]), leftup) + 1; + } + leftup = temp; // Ϊһֵ dp[i-1, j-1] + } + } + return dp[m]; +} + +/* Driver Code */ +int main() { + string s = "bag"; + string t = "pack"; + int n = s.length(), m = t.length(); + + // + int res = editDistanceDFS(s, t, n, m); + cout << " " << s << " Ϊ " << t << " Ҫ༭ " << res << " \n"; + + // 仯 + vector> mem(n + 1, vector(m + 1, -1)); + res = editDistanceDFSMem(s, t, mem, n, m); + cout << " " << s << " Ϊ " << t << " Ҫ༭ " << res << " \n"; + + // ̬滮 + res = editDistanceDP(s, t); + cout << " " << s << " Ϊ " << t << " Ҫ༭ " << res << " \n"; + + // ռŻĶ̬滮 + res = editDistanceDPComp(s, t); + cout << " " << s << " Ϊ " << t << " Ҫ༭ " << res << " \n"; + + return 0; +} diff --git a/chapter_dynamic_programming/knapsack.cpp b/chapter_dynamic_programming/knapsack.cpp new file mode 100644 index 0000000..c15f165 --- /dev/null +++ b/chapter_dynamic_programming/knapsack.cpp @@ -0,0 +1,109 @@ +#include +#include +#include + +using namespace std; + +/* 0-1 */ +int knapsackDFS(vector &wgt, vector &val, int i, int c) { + // ѡƷ򱳰ʣ򷵻ؼֵ 0 + if (i == 0 || c == 0) { + return 0; + } + // ֻѡ񲻷뱳 + if (wgt[i - 1] > c) { + return knapsackDFS(wgt, val, i - 1, c); + } + // 㲻ͷƷ i ֵ + int no = knapsackDFS(wgt, val, i - 1, c); + int yes = knapsackDFS(wgt, val, i - 1, c - wgt[i - 1]) + val[i - 1]; + // ַмֵһ + return max(no, yes); +} + +/* 0-1 仯 */ +int knapsackDFSMem(vector &wgt, vector &val, vector> &mem, int i, int c) { + // ѡƷ򱳰ʣ򷵻ؼֵ 0 + if (i == 0 || c == 0) { + return 0; + } + // м¼ֱӷ + if (mem[i][c] != -1) { + return mem[i][c]; + } + // ֻѡ񲻷뱳 + if (wgt[i - 1] > c) { + return knapsackDFSMem(wgt, val, mem, i - 1, c); + } + // 㲻ͷƷ i ֵ + int no = knapsackDFSMem(wgt, val, mem, i - 1, c); + int yes = knapsackDFSMem(wgt, val, mem, i - 1, c - wgt[i - 1]) + val[i - 1]; + // ¼ַмֵһ + mem[i][c] = max(no, yes); + return mem[i][c]; +} + +/* 0-1 ̬滮 */ +int knapsackDP(vector &wgt, vector &val, int cap) { + int n = wgt.size(); + // ʼ dp + vector> dp(n + 1, vector(cap + 1, 0)); + // ״̬ת + for (int i = 1; i <= n; i++) { + for (int c = 1; c <= cap; c++) { + if (wgt[i - 1] > c) { + // ѡƷ i + dp[i][c] = dp[i - 1][c]; + } else { + // ѡѡƷ i ַĽϴֵ + dp[i][c] = max(dp[i - 1][c], dp[i - 1][c - wgt[i - 1]] + val[i - 1]); + } + } + } + return dp[n][cap]; +} + +/* 0-1 ռŻĶ̬滮 */ +int knapsackDPComp(vector &wgt, vector &val, int cap) { + int n = wgt.size(); + // ʼ dp + vector dp(cap + 1, 0); + // ״̬ת + for (int i = 1; i <= n; i++) { + // + for (int c = cap; c >= 1; c--) { + if (wgt[i - 1] <= c) { + // ѡѡƷ i ַĽϴֵ + dp[c] = max(dp[c], dp[c - wgt[i - 1]] + val[i - 1]); + } + } + } + return dp[cap]; +} + +/* Driver Code */ +int main() { + vector wgt = {10, 20, 30, 40, 50}; + vector val = {50, 120, 150, 210, 240}; + int cap = 50; + int n = wgt.size(); + + // + int res = knapsackDFS(wgt, val, n, cap); + cout << "ƷֵΪ " << res << endl; + + // 仯 + vector> mem(n + 1, vector(cap + 1, -1)); + res = knapsackDFSMem(wgt, val, mem, n, cap); + cout << "ƷֵΪ " << res << endl; + + // ̬滮 + res = knapsackDP(wgt, val, cap); + cout << "ƷֵΪ " << res << endl; + + // ռŻĶ̬滮 + res = knapsackDPComp(wgt, val, cap); + cout << "ƷֵΪ " << res << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/min_cost_climbing_stairs_dp.cpp b/chapter_dynamic_programming/min_cost_climbing_stairs_dp.cpp new file mode 100644 index 0000000..578b60e --- /dev/null +++ b/chapter_dynamic_programming/min_cost_climbing_stairs_dp.cpp @@ -0,0 +1,53 @@ +/** + * File: min_cost_climbing_stairs_dp.cpp + * Created Time: 2023-06-30 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ¥Сۣ̬滮 */ +int minCostClimbingStairsDP(vector &cost) { + int n = cost.size() - 1; + if (n == 1 || n == 2) + return cost[n]; + // ʼ dp ڴ洢Ľ + vector dp(n + 1); + // ʼ״̬ԤСĽ + dp[1] = cost[1]; + dp[2] = cost[2]; + // ״̬תƣӽСϴ + for (int i = 3; i <= n; i++) { + dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]; + } + return dp[n]; +} + +/* ¥СۣռŻĶ̬滮 */ +int minCostClimbingStairsDPComp(vector &cost) { + int n = cost.size() - 1; + if (n == 1 || n == 2) + return cost[n]; + int a = cost[1], b = cost[2]; + for (int i = 3; i <= n; i++) { + int tmp = b; + b = min(a, tmp) + cost[i]; + a = tmp; + } + return b; +} + +/* Driver Code */ +int main() { + vector cost = {0, 1, 10, 1, 1, 1, 10, 1, 1, 10, 1}; + cout << "¥ݵĴбΪ "; + printVector(cost); + + int res = minCostClimbingStairsDP(cost); + cout << "¥ݵʹΪ " << res << endl; + + res = minCostClimbingStairsDPComp(cost); + cout << "¥ݵʹΪ " << res << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/min_path_sum.cpp b/chapter_dynamic_programming/min_path_sum.cpp new file mode 100644 index 0000000..70f6a2b --- /dev/null +++ b/chapter_dynamic_programming/min_path_sum.cpp @@ -0,0 +1,116 @@ +/** + * File: min_path_sum.cpp + * Created Time: 2023-07-10 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* С·ͣ */ +int minPathSumDFS(vector> &grid, int i, int j) { + // ΪϽǵԪֹ + if (i == 0 && j == 0) { + return grid[0][0]; + } + // Խ磬򷵻 + + if (i < 0 || j < 0) { + return INT_MAX; + } + // Ͻǵ (i-1, j) (i, j-1) С· + int up = minPathSumDFS(grid, i - 1, j); + int left = minPathSumDFS(grid, i, j - 1); + // شϽǵ (i, j) С· + return min(left, up) != INT_MAX ? min(left, up) + grid[i][j] : INT_MAX; +} + +/* С·ͣ仯 */ +int minPathSumDFSMem(vector> &grid, vector> &mem, int i, int j) { + // ΪϽǵԪֹ + if (i == 0 && j == 0) { + return grid[0][0]; + } + // Խ磬򷵻 + + if (i < 0 || j < 0) { + return INT_MAX; + } + // м¼ֱӷ + if (mem[i][j] != -1) { + return mem[i][j]; + } + // ߺϱߵԪС· + int up = minPathSumDFSMem(grid, mem, i - 1, j); + int left = minPathSumDFSMem(grid, mem, i, j - 1); + // ¼Ͻǵ (i, j) С· + mem[i][j] = min(left, up) != INT_MAX ? min(left, up) + grid[i][j] : INT_MAX; + return mem[i][j]; +} + +/* С·̬ͣ滮 */ +int minPathSumDP(vector> &grid) { + int n = grid.size(), m = grid[0].size(); + // ʼ dp + vector> dp(n, vector(m)); + dp[0][0] = grid[0][0]; + // ״̬תƣ + for (int j = 1; j < m; j++) { + dp[0][j] = dp[0][j - 1] + grid[0][j]; + } + // ״̬תƣ + for (int i = 1; i < n; i++) { + dp[i][0] = dp[i - 1][0] + grid[i][0]; + } + // ״̬תƣк + for (int i = 1; i < n; i++) { + for (int j = 1; j < m; j++) { + dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j]; + } + } + return dp[n - 1][m - 1]; +} + +/* С·ͣռŻĶ̬滮 */ +int minPathSumDPComp(vector> &grid) { + int n = grid.size(), m = grid[0].size(); + // ʼ dp + vector dp(m); + // ״̬תƣ + dp[0] = grid[0][0]; + for (int j = 1; j < m; j++) { + dp[j] = dp[j - 1] + grid[0][j]; + } + // ״̬תƣ + for (int i = 1; i < n; i++) { + // ״̬תƣ + dp[0] = dp[0] + grid[i][0]; + // ״̬תƣ + for (int j = 1; j < m; j++) { + dp[j] = min(dp[j - 1], dp[j]) + grid[i][j]; + } + } + return dp[m - 1]; +} + +/* Driver Code */ +int main() { + vector> grid = {{1, 3, 1, 5}, {2, 2, 4, 2}, {5, 3, 2, 1}, {4, 3, 5, 2}}; + int n = grid.size(), m = grid[0].size(); + + // + int res = minPathSumDFS(grid, n - 1, m - 1); + cout << "Ͻǵ½ǵС·Ϊ " << res << endl; + + // 仯 + vector> mem(n, vector(m, -1)); + res = minPathSumDFSMem(grid, mem, n - 1, m - 1); + cout << "Ͻǵ½ǵС·Ϊ " << res << endl; + + // ̬滮 + res = minPathSumDP(grid); + cout << "Ͻǵ½ǵС·Ϊ " << res << endl; + + // ռŻĶ̬滮 + res = minPathSumDPComp(grid); + cout << "Ͻǵ½ǵС·Ϊ " << res << endl; + + return 0; +} diff --git a/chapter_dynamic_programming/unbounded_knapsack.cpp b/chapter_dynamic_programming/unbounded_knapsack.cpp new file mode 100644 index 0000000..5956027 --- /dev/null +++ b/chapter_dynamic_programming/unbounded_knapsack.cpp @@ -0,0 +1,64 @@ +/** + * File: unbounded_knapsack.cpp + * Created Time: 2023-07-11 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ȫ̬滮 */ +int unboundedKnapsackDP(vector &wgt, vector &val, int cap) { + int n = wgt.size(); + // ʼ dp + vector> dp(n + 1, vector(cap + 1, 0)); + // ״̬ת + for (int i = 1; i <= n; i++) { + for (int c = 1; c <= cap; c++) { + if (wgt[i - 1] > c) { + // ѡƷ i + dp[i][c] = dp[i - 1][c]; + } else { + // ѡѡƷ i ַĽϴֵ + dp[i][c] = max(dp[i - 1][c], dp[i][c - wgt[i - 1]] + val[i - 1]); + } + } + } + return dp[n][cap]; +} + +/* ȫռŻĶ̬滮 */ +int unboundedKnapsackDPComp(vector &wgt, vector &val, int cap) { + int n = wgt.size(); + // ʼ dp + vector dp(cap + 1, 0); + // ״̬ת + for (int i = 1; i <= n; i++) { + for (int c = 1; c <= cap; c++) { + if (wgt[i - 1] > c) { + // ѡƷ i + dp[c] = dp[c]; + } else { + // ѡѡƷ i ַĽϴֵ + dp[c] = max(dp[c], dp[c - wgt[i - 1]] + val[i - 1]); + } + } + } + return dp[cap]; +} + +/* Driver code */ +int main() { + vector wgt = {1, 2, 3}; + vector val = {5, 11, 15}; + int cap = 4; + + // ̬滮 + int res = unboundedKnapsackDP(wgt, val, cap); + cout << "ƷֵΪ " << res << endl; + + // ռŻĶ̬滮 + res = unboundedKnapsackDPComp(wgt, val, cap); + cout << "ƷֵΪ " << res << endl; + + return 0; +} diff --git a/chapter_graph/CMakeLists.txt b/chapter_graph/CMakeLists.txt new file mode 100644 index 0000000..4a56ce3 --- /dev/null +++ b/chapter_graph/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(graph_bfs graph_bfs.cpp) +add_executable(graph_dfs graph_dfs.cpp) +# add_executable(graph_adjacency_list graph_adjacency_list.cpp) +add_executable(graph_adjacency_list_test graph_adjacency_list_test.cpp) +add_executable(graph_adjacency_matrix graph_adjacency_matrix.cpp) diff --git a/chapter_graph/graph_adjacency_list.cpp b/chapter_graph/graph_adjacency_list.cpp new file mode 100644 index 0000000..3538732 --- /dev/null +++ b/chapter_graph/graph_adjacency_list.cpp @@ -0,0 +1,90 @@ +/** + * File: graph_adjacency_list.cpp + * Created Time: 2023-02-09 + * Author: what-is-me (whatisme@outlook.jp), krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ڽӱʵֵͼ */ +class GraphAdjList { + public: + // ڽӱkey㣬valueöڽӶ + unordered_map> adjList; + + /* vector ɾָڵ */ + void remove(vector &vec, Vertex *vet) { + for (int i = 0; i < vec.size(); i++) { + if (vec[i] == vet) { + vec.erase(vec.begin() + i); + break; + } + } + } + + /* 췽 */ + GraphAdjList(const vector> &edges) { + // жͱ + for (const vector &edge : edges) { + addVertex(edge[0]); + addVertex(edge[1]); + addEdge(edge[0], edge[1]); + } + } + + /* ȡ */ + int size() { + return adjList.size(); + } + + /* ӱ */ + void addEdge(Vertex *vet1, Vertex *vet2) { + if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2) + throw invalid_argument("ڶ"); + // ӱ vet1 - vet2 + adjList[vet1].push_back(vet2); + adjList[vet2].push_back(vet1); + } + + /* ɾ */ + void removeEdge(Vertex *vet1, Vertex *vet2) { + if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2) + throw invalid_argument("ڶ"); + // ɾ vet1 - vet2 + remove(adjList[vet1], vet2); + remove(adjList[vet2], vet1); + } + + /* Ӷ */ + void addVertex(Vertex *vet) { + if (adjList.count(vet)) + return; + // ڽӱһ + adjList[vet] = vector(); + } + + /* ɾ */ + void removeVertex(Vertex *vet) { + if (!adjList.count(vet)) + throw invalid_argument("ڶ"); + // ڽӱɾ vet Ӧ + adjList.erase(vet); + // ɾа vet ı + for (auto &adj : adjList) { + remove(adj.second, vet); + } + } + + /* ӡڽӱ */ + void print() { + cout << "ڽӱ =" << endl; + for (auto &adj : adjList) { + const auto &key = adj.first; + const auto &vec = adj.second; + cout << key->val << ": "; + printVector(vetsToVals(vec)); + } + } +}; + +// graph_adjacency_list_test.cpp diff --git a/chapter_graph/graph_adjacency_list_test.cpp b/chapter_graph/graph_adjacency_list_test.cpp new file mode 100644 index 0000000..fdb200e --- /dev/null +++ b/chapter_graph/graph_adjacency_list_test.cpp @@ -0,0 +1,49 @@ +/** + * File: graph_adjacency_list_test.cpp + * Created Time: 2023-02-09 + * Author: what-is-me (whatisme@outlook.jp), krahets (krahets@163.com) + */ + +#include "./graph_adjacency_list.cpp" + +/* Driver Code */ +int main() { + /* ʼͼ */ + vector v = valsToVets(vector{1, 3, 2, 5, 4}); + vector> edges = {{v[0], v[1]}, {v[0], v[3]}, {v[1], v[2]}, + {v[2], v[3]}, {v[2], v[4]}, {v[3], v[4]}}; + GraphAdjList graph(edges); + cout << "\nʼͼΪ" << endl; + graph.print(); + + /* ӱ */ + // 1, 2 v[0], v[2] + graph.addEdge(v[0], v[2]); + cout << "\nӱ 1-2 ͼΪ" << endl; + graph.print(); + + /* ɾ */ + // 1, 3 v[0], v[1] + graph.removeEdge(v[0], v[1]); + cout << "\nɾ 1-3 ͼΪ" << endl; + graph.print(); + + /* Ӷ */ + Vertex *v5 = new Vertex(6); + graph.addVertex(v5); + cout << "\nӶ 6 ͼΪ" << endl; + graph.print(); + + /* ɾ */ + // 3 v[1] + graph.removeVertex(v[1]); + cout << "\nɾ 3 ͼΪ" << endl; + graph.print(); + + // ͷڴ + for (Vertex *vet : v) { + delete vet; + } + + return 0; +} diff --git a/chapter_graph/graph_adjacency_matrix.cpp b/chapter_graph/graph_adjacency_matrix.cpp new file mode 100644 index 0000000..42f696b --- /dev/null +++ b/chapter_graph/graph_adjacency_matrix.cpp @@ -0,0 +1,127 @@ +/** + * File: graph_adjacency_matrix.cpp + * Created Time: 2023-02-09 + * Author: what-is-me (whatisme@outlook.jp) + */ + +#include "../utils/common.hpp" + +/* ڽӾʵֵͼ */ +class GraphAdjMat { + vector vertices; // бԪشֵ + vector> adjMat; // ڽӾӦ + + public: + /* 췽 */ + GraphAdjMat(const vector &vertices, const vector> &edges) { + // Ӷ + for (int val : vertices) { + addVertex(val); + } + // ӱ + // ע⣬edges ԪشӦ vertices Ԫ + for (const vector &edge : edges) { + addEdge(edge[0], edge[1]); + } + } + + /* ȡ */ + int size() const { + return vertices.size(); + } + + /* Ӷ */ + void addVertex(int val) { + int n = size(); + // 򶥵б¶ֵ + vertices.push_back(val); + // ڽӾһ + adjMat.emplace_back(vector(n, 0)); + // ڽӾһ + for (vector &row : adjMat) { + row.push_back(0); + } + } + + /* ɾ */ + void removeVertex(int index) { + if (index >= size()) { + throw out_of_range("㲻"); + } + // ڶбƳ index Ķ + vertices.erase(vertices.begin() + index); + // ڽӾɾ index + adjMat.erase(adjMat.begin() + index); + // ڽӾɾ index + for (vector &row : adjMat) { + row.erase(row.begin() + index); + } + } + + /* ӱ */ + // i, j Ӧ vertices Ԫ + void addEdge(int i, int j) { + // Խȴ + if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) { + throw out_of_range("㲻"); + } + // ͼУڽӾԽ߶Գƣ (i, j) == (j, i) + adjMat[i][j] = 1; + adjMat[j][i] = 1; + } + + /* ɾ */ + // i, j Ӧ vertices Ԫ + void removeEdge(int i, int j) { + // Խȴ + if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) { + throw out_of_range("㲻"); + } + adjMat[i][j] = 0; + adjMat[j][i] = 0; + } + + /* ӡڽӾ */ + void print() { + cout << "б = "; + printVector(vertices); + cout << "ڽӾ =" << endl; + printVectorMatrix(adjMat); + } +}; + +/* Driver Code */ +int main() { + /* ʼͼ */ + // ע⣬edges ԪشӦ vertices Ԫ + vector vertices = {1, 3, 2, 5, 4}; + vector> edges = {{0, 1}, {0, 3}, {1, 2}, {2, 3}, {2, 4}, {3, 4}}; + GraphAdjMat graph(vertices, edges); + cout << "\nʼͼΪ" << endl; + graph.print(); + + /* ӱ */ + // 1, 2 ֱΪ 0, 2 + graph.addEdge(0, 2); + cout << "\nӱ 1-2 ͼΪ" << endl; + graph.print(); + + /* ɾ */ + // 1, 3 ֱΪ 0, 1 + graph.removeEdge(0, 1); + cout << "\nɾ 1-3 ͼΪ" << endl; + graph.print(); + + /* Ӷ */ + graph.addVertex(6); + cout << "\nӶ 6 ͼΪ" << endl; + graph.print(); + + /* ɾ */ + // 3 Ϊ 1 + graph.removeVertex(1); + cout << "\nɾ 3 ͼΪ" << endl; + graph.print(); + + return 0; +} diff --git a/chapter_graph/graph_bfs.cpp b/chapter_graph/graph_bfs.cpp new file mode 100644 index 0000000..c2a195b --- /dev/null +++ b/chapter_graph/graph_bfs.cpp @@ -0,0 +1,59 @@ +/** + * File: graph_bfs.cpp + * Created Time: 2023-03-02 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" +#include "./graph_adjacency_list.cpp" + +/* ȱ */ +// ʹڽӱʾͼԱȡָڽӶ +vector graphBFS(GraphAdjList &graph, Vertex *startVet) { + // + vector res; + // ϣڼ¼ѱʹĶ + unordered_set visited = {startVet}; + // ʵ BFS + queue que; + que.push(startVet); + // Զ vet Ϊ㣬ѭֱж + while (!que.empty()) { + Vertex *vet = que.front(); + que.pop(); // ׶ + res.push_back(vet); // ¼ʶ + // öڽӶ + for (auto adjVet : graph.adjList[vet]) { + if (visited.count(adjVet)) + continue; // ѱʵĶ + que.push(adjVet); // ֻδʵĶ + visited.emplace(adjVet); // Ǹöѱ + } + } + // ض + return res; +} + +/* Driver Code */ +int main() { + /* ʼͼ */ + vector v = valsToVets({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + vector> edges = {{v[0], v[1]}, {v[0], v[3]}, {v[1], v[2]}, {v[1], v[4]}, + {v[2], v[5]}, {v[3], v[4]}, {v[3], v[6]}, {v[4], v[5]}, + {v[4], v[7]}, {v[5], v[8]}, {v[6], v[7]}, {v[7], v[8]}}; + GraphAdjList graph(edges); + cout << "\nʼͼΪ\\n"; + graph.print(); + + /* ȱ */ + vector res = graphBFS(graph, v[0]); + cout << "\nȱBFSΪ" << endl; + printVector(vetsToVals(res)); + + // ͷڴ + for (Vertex *vet : v) { + delete vet; + } + + return 0; +} diff --git a/chapter_graph/graph_dfs.cpp b/chapter_graph/graph_dfs.cpp new file mode 100644 index 0000000..d29f962 --- /dev/null +++ b/chapter_graph/graph_dfs.cpp @@ -0,0 +1,55 @@ +/** + * File: graph_dfs.cpp + * Created Time: 2023-03-02 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" +#include "./graph_adjacency_list.cpp" + +/* ȱ */ +void dfs(GraphAdjList &graph, unordered_set &visited, vector &res, Vertex *vet) { + res.push_back(vet); // ¼ʶ + visited.emplace(vet); // Ǹöѱ + // öڽӶ + for (Vertex *adjVet : graph.adjList[vet]) { + if (visited.count(adjVet)) + continue; // ѱʵĶ + // ݹڽӶ + dfs(graph, visited, res, adjVet); + } +} + +/* ȱ */ +// ʹڽӱʾͼԱȡָڽӶ +vector graphDFS(GraphAdjList &graph, Vertex *startVet) { + // + vector res; + // ϣڼ¼ѱʹĶ + unordered_set visited; + dfs(graph, visited, res, startVet); + return res; +} + +/* Driver Code */ +int main() { + /* ʼͼ */ + vector v = valsToVets(vector{0, 1, 2, 3, 4, 5, 6}); + vector> edges = {{v[0], v[1]}, {v[0], v[3]}, {v[1], v[2]}, + {v[2], v[5]}, {v[4], v[5]}, {v[5], v[6]}}; + GraphAdjList graph(edges); + cout << "\nʼͼΪ" << endl; + graph.print(); + + /* ȱ */ + vector res = graphDFS(graph, v[0]); + cout << "\nȱDFSΪ" << endl; + printVector(vetsToVals(res)); + + // ͷڴ + for (Vertex *vet : v) { + delete vet; + } + + return 0; +} diff --git a/chapter_greedy/CMakeLists.txt b/chapter_greedy/CMakeLists.txt new file mode 100644 index 0000000..9178866 --- /dev/null +++ b/chapter_greedy/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(coin_change_greedy coin_change_greedy.cpp) +add_executable(fractional_knapsack fractional_knapsack.cpp) +add_executable(max_capacity max_capacity.cpp) \ No newline at end of file diff --git a/chapter_greedy/coin_change_greedy.cpp b/chapter_greedy/coin_change_greedy.cpp new file mode 100644 index 0000000..bef764f --- /dev/null +++ b/chapter_greedy/coin_change_greedy.cpp @@ -0,0 +1,60 @@ +/** + * File: coin_change_greedy.cpp + * Created Time: 2023-07-20 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Ǯһ̰ */ +int coinChangeGreedy(vector &coins, int amt) { + // coins б + int i = coins.size() - 1; + int count = 0; + // ѭ̰ѡֱʣ + while (amt > 0) { + // ҵСӽʣӲ + while (i > 0 && coins[i] > amt) { + i--; + } + // ѡ coins[i] + amt -= coins[i]; + count++; + } + // δҵз򷵻 -1 + return amt == 0 ? count : -1; +} + +/* Driver Code */ +int main() { + // ̰ģܹ֤ҵȫŽ + vector coins = {1, 5, 10, 20, 50, 100}; + int amt = 186; + int res = coinChangeGreedy(coins, amt); + cout << "\ncoins = "; + printVector(coins); + cout << "amt = " << amt << endl; + cout << "յ " << amt << " ӲΪ " << res << endl; + + // ̰ģ޷֤ҵȫŽ + coins = {1, 20, 50}; + amt = 60; + res = coinChangeGreedy(coins, amt); + cout << "\ncoins = "; + printVector(coins); + cout << "amt = " << amt << endl; + cout << "յ " << amt << " ӲΪ " << res << endl; + cout << "ʵҪΪ 3 20 + 20 + 20" << endl; + + // ̰ģ޷֤ҵȫŽ + coins = {1, 49, 50}; + amt = 98; + res = coinChangeGreedy(coins, amt); + cout << "\ncoins = "; + printVector(coins); + cout << "amt = " << amt << endl; + cout << "յ " << amt << " ӲΪ " << res << endl; + cout << "ʵҪΪ 2 49 + 49" << endl; + + return 0; +} diff --git a/chapter_greedy/fractional_knapsack.cpp b/chapter_greedy/fractional_knapsack.cpp new file mode 100644 index 0000000..2eaebbd --- /dev/null +++ b/chapter_greedy/fractional_knapsack.cpp @@ -0,0 +1,56 @@ +/** + * File: fractional_knapsack.cpp + * Created Time: 2023-07-20 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Ʒ */ +class Item { + public: + int w; // Ʒ + int v; // Ʒֵ + + Item(int w, int v) : w(w), v(v) { + } +}; + +/* ̰ */ +double fractionalKnapsack(vector &wgt, vector &val, int cap) { + // Ʒбԣֵ + vector items; + for (int i = 0; i < wgt.size(); i++) { + items.push_back(Item(wgt[i], val[i])); + } + // յλֵ item.v / item.w Ӹߵͽ + sort(items.begin(), items.end(), [](Item &a, Item &b) { return (double)a.v / a.w > (double)b.v / b.w; }); + // ѭ̰ѡ + double res = 0; + for (auto &item : items) { + if (item.w <= cap) { + // ʣ㣬򽫵ǰƷװ + res += item.v; + cap -= item.w; + } else { + // ʣ㣬򽫵ǰƷһװ + res += (double)item.v / item.w * cap; + // ʣѭ + break; + } + } + return res; +} + +/* Driver Code */ +int main() { + vector wgt = {10, 20, 30, 40, 50}; + vector val = {50, 120, 150, 210, 240}; + int cap = 50; + + // ̰㷨 + double res = fractionalKnapsack(wgt, val, cap); + cout << "ƷֵΪ " << res << endl; + + return 0; +} diff --git a/chapter_greedy/max_capacity.cpp b/chapter_greedy/max_capacity.cpp new file mode 100644 index 0000000..555cd06 --- /dev/null +++ b/chapter_greedy/max_capacity.cpp @@ -0,0 +1,39 @@ +/** + * File: max_capacity.cpp + * Created Time: 2023-07-21 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ̰ */ +int maxCapacity(vector &ht) { + // ʼ i, jʹ + int i = 0, j = ht.size() - 1; + // ʼΪ 0 + int res = 0; + // ѭ̰ѡֱ + while (i < j) { + // + int cap = min(ht[i], ht[j]) * (j - i); + res = max(res, cap); + // ƶ̰ + if (ht[i] < ht[j]) { + i++; + } else { + j--; + } + } + return res; +} + +/* Driver Code */ +int main() { + vector ht = {3, 8, 5, 2, 7, 7, 3, 4}; + + // ̰㷨 + int res = maxCapacity(ht); + cout << "Ϊ " << res << endl; + + return 0; +} diff --git a/chapter_greedy/max_product_cutting.cpp b/chapter_greedy/max_product_cutting.cpp new file mode 100644 index 0000000..65fe893 --- /dev/null +++ b/chapter_greedy/max_product_cutting.cpp @@ -0,0 +1,39 @@ +/** + * File: max_product_cutting.cpp + * Created Time: 2023-07-21 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* зֳ˻̰ */ +int maxProductCutting(int n) { + // n <= 3 ʱзֳһ 1 + if (n <= 3) { + return 1 * (n - 1); + } + // ̰ĵзֳ 3 a Ϊ 3 ĸb Ϊ + int a = n / 3; + int b = n % 3; + if (b == 1) { + // Ϊ 1 ʱһ 1 * 3 תΪ 2 * 2 + return (int)pow(3, a - 1) * 2 * 2; + } + if (b == 2) { + // Ϊ 2 ʱ + return (int)pow(3, a) * 2; + } + // Ϊ 0 ʱ + return (int)pow(3, a); +} + +/* Driver Code */ +int main() { + int n = 58; + + // ̰㷨 + int res = maxProductCutting(n); + cout << "зֳ˻Ϊ" << res << endl; + + return 0; +} diff --git a/chapter_hashing/CMakeLists.txt b/chapter_hashing/CMakeLists.txt new file mode 100644 index 0000000..6b583ef --- /dev/null +++ b/chapter_hashing/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(hash_map hash_map.cpp) +add_executable(array_hash_map_test array_hash_map_test.cpp) +add_executable(hash_map_chaining hash_map_chaining.cpp) +add_executable(hash_map_open_addressing hash_map_open_addressing.cpp) +add_executable(simple_hash simple_hash.cpp) +add_executable(built_in_hash built_in_hash.cpp) \ No newline at end of file diff --git a/chapter_hashing/array_hash_map.cpp b/chapter_hashing/array_hash_map.cpp new file mode 100644 index 0000000..d8838c4 --- /dev/null +++ b/chapter_hashing/array_hash_map.cpp @@ -0,0 +1,110 @@ +/** + * File: array_hash_map.cpp + * Created Time: 2022-12-14 + * Author: msk397 (machangxinq@gmail.com) + */ + +#include "../utils/common.hpp" + +/* ֵ */ +struct Pair { + public: + int key; + string val; + Pair(int key, string val) { + this->key = key; + this->val = val; + } +}; + +/* ʵֵĹϣ */ +class ArrayHashMap { + private: + vector buckets; + + public: + ArrayHashMap() { + // ʼ飬 100 Ͱ + buckets = vector(100); + } + + ~ArrayHashMap() { + // ͷڴ + for (const auto &bucket : buckets) { + delete bucket; + } + buckets.clear(); + } + + /* ϣ */ + int hashFunc(int key) { + int index = key % 100; + return index; + } + + /* ѯ */ + string get(int key) { + int index = hashFunc(key); + Pair *pair = buckets[index]; + if (pair == nullptr) + return ""; + return pair->val; + } + + /* Ӳ */ + void put(int key, string val) { + Pair *pair = new Pair(key, val); + int index = hashFunc(key); + buckets[index] = pair; + } + + /* ɾ */ + void remove(int key) { + int index = hashFunc(key); + // ͷڴ沢Ϊ nullptr + delete buckets[index]; + buckets[index] = nullptr; + } + + /* ȡмֵ */ + vector pairSet() { + vector pairSet; + for (Pair *pair : buckets) { + if (pair != nullptr) { + pairSet.push_back(pair); + } + } + return pairSet; + } + + /* ȡм */ + vector keySet() { + vector keySet; + for (Pair *pair : buckets) { + if (pair != nullptr) { + keySet.push_back(pair->key); + } + } + return keySet; + } + + /* ȡֵ */ + vector valueSet() { + vector valueSet; + for (Pair *pair : buckets) { + if (pair != nullptr) { + valueSet.push_back(pair->val); + } + } + return valueSet; + } + + /* ӡϣ */ + void print() { + for (Pair *kv : pairSet()) { + cout << kv->key << " -> " << kv->val << endl; + } + } +}; + +// array_hash_map_test.cpp diff --git a/chapter_hashing/array_hash_map_test.cpp b/chapter_hashing/array_hash_map_test.cpp new file mode 100644 index 0000000..4b3ccc8 --- /dev/null +++ b/chapter_hashing/array_hash_map_test.cpp @@ -0,0 +1,52 @@ +/** + * File: array_hash_map_test.cpp + * Created Time: 2022-12-14 + * Author: msk397 (machangxinq@gmail.com) + */ + +#include "./array_hash_map.cpp" + +/* Driver Code */ +int main() { + /* 初始化哈希表 */ + ArrayHashMap map = ArrayHashMap(); + + /* 添加操作 */ + // 在哈希表中添加键值对 (key, value) + map.put(12836, "小哈"); + map.put(15937, "小啰"); + map.put(16750, "小算"); + map.put(13276, "小法"); + map.put(10583, "小鸭"); + cout << "\n添加完成后,哈希表为\nKey -> Value" << endl; + map.print(); + + /* 查询操作 */ + // 向哈希表中输入键 key ,得到值 value + string name = map.get(15937); + cout << "\n输入学号 15937 ,查询到姓名 " << name << endl; + + /* 删除操作 */ + // 在哈希表中删除键值对 (key, value) + map.remove(10583); + cout << "\n删除 10583 后,哈希表为\nKey -> Value" << endl; + map.print(); + + /* 遍历哈希表 */ + cout << "\n遍历键值对 Key->Value" << endl; + for (auto kv : map.pairSet()) { + cout << kv->key << " -> " << kv->val << endl; + } + + cout << "\n单独遍历键 Key" << endl; + for (auto key : map.keySet()) { + cout << key << endl; + } + + cout << "\n单独遍历值 Value" << endl; + for (auto val : map.valueSet()) { + cout << val << endl; + } + + return 0; +} diff --git a/chapter_hashing/built_in_hash.cpp b/chapter_hashing/built_in_hash.cpp new file mode 100644 index 0000000..d7d48ab --- /dev/null +++ b/chapter_hashing/built_in_hash.cpp @@ -0,0 +1,29 @@ +/** + * File: built_in_hash.cpp + * Created Time: 2023-06-21 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Driver Code */ +int main() { + int num = 3; + size_t hashNum = hash()(num); + cout << " " << num << " ĹϣֵΪ " << hashNum << "\n"; + + bool bol = true; + size_t hashBol = hash()(bol); + cout << " " << bol << " ĹϣֵΪ " << hashBol << "\n"; + + double dec = 3.14159; + size_t hashDec = hash()(dec); + cout << "С " << dec << " ĹϣֵΪ " << hashDec << "\n"; + + string str = "Hello 㷨"; + size_t hashStr = hash()(str); + cout << "ַ " << str << " ĹϣֵΪ " << hashStr << "\n"; + + // C++ У std:hash() ṩ͵Ĺϣֵ + // 顢ĹϣֵҪʵ +} diff --git a/chapter_hashing/hash_map.cpp b/chapter_hashing/hash_map.cpp new file mode 100644 index 0000000..8875032 --- /dev/null +++ b/chapter_hashing/hash_map.cpp @@ -0,0 +1,46 @@ +/** + * File: hash_map.cpp + * Created Time: 2022-12-14 + * Author: msk397 (machangxinq@gmail.com) + */ + +#include "../utils/common.hpp" + +/* Driver Code */ +int main() { + /* 初始化哈希表 */ + unordered_map map; + + /* 添加操作 */ + // 在哈希表中添加键值对 (key, value) + map[12836] = "小哈"; + map[15937] = "小啰"; + map[16750] = "小算"; + map[13276] = "小法"; + map[10583] = "小鸭"; + cout << "\n添加完成后,哈希表为\nKey -> Value" << endl; + printHashMap(map); + + /* 查询操作 */ + // 向哈希表中输入键 key ,得到值 value + string name = map[15937]; + cout << "\n输入学号 15937 ,查询到姓名 " << name << endl; + + /* 删除操作 */ + // 在哈希表中删除键值对 (key, value) + map.erase(10583); + cout << "\n删除 10583 后,哈希表为\nKey -> Value" << endl; + printHashMap(map); + + /* 遍历哈希表 */ + cout << "\n遍历键值对 Key->Value" << endl; + for (auto kv : map) { + cout << kv.first << " -> " << kv.second << endl; + } + cout << "\n使用迭代器遍历 Key->Value" << endl; + for (auto iter = map.begin(); iter != map.end(); iter++) { + cout << iter->first << "->" << iter->second << endl; + } + + return 0; +} diff --git a/chapter_hashing/hash_map_chaining.cpp b/chapter_hashing/hash_map_chaining.cpp new file mode 100644 index 0000000..4fc373e --- /dev/null +++ b/chapter_hashing/hash_map_chaining.cpp @@ -0,0 +1,150 @@ +/** + * File: hash_map_chaining.cpp + * Created Time: 2023-06-13 + * Author: krahets (krahets@163.com) + */ + +#include "./array_hash_map.cpp" + +/* 链式地址哈希表 */ +class HashMapChaining { + private: + int size; // 键值对数量 + int capacity; // 哈希表容量 + double loadThres; // 触发扩容的负载因子阈值 + int extendRatio; // 扩容倍数 + vector> buckets; // 桶数组 + + public: + /* 构造方法 */ + HashMapChaining() : size(0), capacity(4), loadThres(2.0 / 3.0), extendRatio(2) { + buckets.resize(capacity); + } + + /* 析构方法 */ + ~HashMapChaining() { + for (auto &bucket : buckets) { + for (Pair *pair : bucket) { + // 释放内存 + delete pair; + } + } + } + + /* 哈希函数 */ + int hashFunc(int key) { + return key % capacity; + } + + /* 负载因子 */ + double loadFactor() { + return (double)size / (double)capacity; + } + + /* 查询操作 */ + string get(int key) { + int index = hashFunc(key); + // 遍历桶,若找到 key ,则返回对应 val + for (Pair *pair : buckets[index]) { + if (pair->key == key) { + return pair->val; + } + } + // 若未找到 key ,则返回空字符串 + return ""; + } + + /* 添加操作 */ + void put(int key, string val) { + // 当负载因子超过阈值时,执行扩容 + if (loadFactor() > loadThres) { + extend(); + } + int index = hashFunc(key); + // 遍历桶,若遇到指定 key ,则更新对应 val 并返回 + for (Pair *pair : buckets[index]) { + if (pair->key == key) { + pair->val = val; + return; + } + } + // 若无该 key ,则将键值对添加至尾部 + buckets[index].push_back(new Pair(key, val)); + size++; + } + + /* 删除操作 */ + void remove(int key) { + int index = hashFunc(key); + auto &bucket = buckets[index]; + // 遍历桶,从中删除键值对 + for (int i = 0; i < bucket.size(); i++) { + if (bucket[i]->key == key) { + Pair *tmp = bucket[i]; + bucket.erase(bucket.begin() + i); // 从中删除键值对 + delete tmp; // 释放内存 + size--; + return; + } + } + } + + /* 扩容哈希表 */ + void extend() { + // 暂存原哈希表 + vector> bucketsTmp = buckets; + // 初始化扩容后的新哈希表 + capacity *= extendRatio; + buckets.clear(); + buckets.resize(capacity); + size = 0; + // 将键值对从原哈希表搬运至新哈希表 + for (auto &bucket : bucketsTmp) { + for (Pair *pair : bucket) { + put(pair->key, pair->val); + // 释放内存 + delete pair; + } + } + } + + /* 打印哈希表 */ + void print() { + for (auto &bucket : buckets) { + cout << "["; + for (Pair *pair : bucket) { + cout << pair->key << " -> " << pair->val << ", "; + } + cout << "]\n"; + } + } +}; + +/* Driver Code */ +int main() { + /* 初始化哈希表 */ + HashMapChaining map = HashMapChaining(); + + /* 添加操作 */ + // 在哈希表中添加键值对 (key, value) + map.put(12836, "小哈"); + map.put(15937, "小啰"); + map.put(16750, "小算"); + map.put(13276, "小法"); + map.put(10583, "小鸭"); + cout << "\n添加完成后,哈希表为\nKey -> Value" << endl; + map.print(); + + /* 查询操作 */ + // 向哈希表中输入键 key ,得到值 value + string name = map.get(13276); + cout << "\n输入学号 13276 ,查询到姓名 " << name << endl; + + /* 删除操作 */ + // 在哈希表中删除键值对 (key, value) + map.remove(12836); + cout << "\n删除 12836 后,哈希表为\nKey -> Value" << endl; + map.print(); + + return 0; +} diff --git a/chapter_hashing/hash_map_open_addressing.cpp b/chapter_hashing/hash_map_open_addressing.cpp new file mode 100644 index 0000000..7f9bf5a --- /dev/null +++ b/chapter_hashing/hash_map_open_addressing.cpp @@ -0,0 +1,171 @@ +/** + * File: hash_map_open_addressing.cpp + * Created Time: 2023-06-13 + * Author: krahets (krahets@163.com) + */ + +#include "./array_hash_map.cpp" + +/* 开放寻址哈希表 */ +class HashMapOpenAddressing { + private: + int size; // 键值对数量 + int capacity = 4; // 哈希表容量 + const double loadThres = 2.0 / 3.0; // 触发扩容的负载因子阈值 + const int extendRatio = 2; // 扩容倍数 + vector buckets; // 桶数组 + Pair *TOMBSTONE = new Pair(-1, "-1"); // 删除标记 + + public: + /* 构造方法 */ + HashMapOpenAddressing() : size(0), buckets(capacity, nullptr) { + } + + /* 析构方法 */ + ~HashMapOpenAddressing() { + for (Pair *pair : buckets) { + if (pair != nullptr && pair != TOMBSTONE) { + delete pair; + } + } + delete TOMBSTONE; + } + + /* 哈希函数 */ + int hashFunc(int key) { + return key % capacity; + } + + /* 负载因子 */ + double loadFactor() { + return (double)size / capacity; + } + + /* 搜索 key 对应的桶索引 */ + int findBucket(int key) { + int index = hashFunc(key); + int firstTombstone = -1; + // 线性探测,当遇到空桶时跳出 + while (buckets[index] != nullptr) { + // 若遇到 key ,返回对应的桶索引 + if (buckets[index]->key == key) { + // 若之前遇到了删除标记,则将键值对移动至该索引处 + if (firstTombstone != -1) { + buckets[firstTombstone] = buckets[index]; + buckets[index] = TOMBSTONE; + return firstTombstone; // 返回移动后的桶索引 + } + return index; // 返回桶索引 + } + // 记录遇到的首个删除标记 + if (firstTombstone == -1 && buckets[index] == TOMBSTONE) { + firstTombstone = index; + } + // 计算桶索引,越过尾部则返回头部 + index = (index + 1) % capacity; + } + // 若 key 不存在,则返回添加点的索引 + return firstTombstone == -1 ? index : firstTombstone; + } + + /* 查询操作 */ + string get(int key) { + // 搜索 key 对应的桶索引 + int index = findBucket(key); + // 若找到键值对,则返回对应 val + if (buckets[index] != nullptr && buckets[index] != TOMBSTONE) { + return buckets[index]->val; + } + // 若键值对不存在,则返回空字符串 + return ""; + } + + /* 添加操作 */ + void put(int key, string val) { + // 当负载因子超过阈值时,执行扩容 + if (loadFactor() > loadThres) { + extend(); + } + // 搜索 key 对应的桶索引 + int index = findBucket(key); + // 若找到键值对,则覆盖 val 并返回 + if (buckets[index] != nullptr && buckets[index] != TOMBSTONE) { + buckets[index]->val = val; + return; + } + // 若键值对不存在,则添加该键值对 + buckets[index] = new Pair(key, val); + size++; + } + + /* 删除操作 */ + void remove(int key) { + // 搜索 key 对应的桶索引 + int index = findBucket(key); + // 若找到键值对,则用删除标记覆盖它 + if (buckets[index] != nullptr && buckets[index] != TOMBSTONE) { + delete buckets[index]; + buckets[index] = TOMBSTONE; + size--; + } + } + + /* 扩容哈希表 */ + void extend() { + // 暂存原哈希表 + vector bucketsTmp = buckets; + // 初始化扩容后的新哈希表 + capacity *= extendRatio; + buckets = vector(capacity, nullptr); + size = 0; + // 将键值对从原哈希表搬运至新哈希表 + for (Pair *pair : bucketsTmp) { + if (pair != nullptr && pair != TOMBSTONE) { + put(pair->key, pair->val); + delete pair; + } + } + } + + /* 打印哈希表 */ + void print() { + for (Pair *pair : buckets) { + if (pair == nullptr) { + cout << "nullptr" << endl; + } else if (pair == TOMBSTONE) { + cout << "TOMBSTONE" << endl; + } else { + cout << pair->key << " -> " << pair->val << endl; + } + } + } +}; + +/* Driver Code */ +int main() { + // 初始化哈希表 + HashMapOpenAddressing hashmap; + + // 添加操作 + // 在哈希表中添加键值对 (key, val) + hashmap.put(12836, "小哈"); + hashmap.put(15937, "小啰"); + hashmap.put(16750, "小算"); + hashmap.put(13276, "小法"); + hashmap.put(10583, "小鸭"); + cout << "\n添加完成后,哈希表为\nKey -> Value" << endl; + hashmap.print(); + + // 查询操作 + // 向哈希表中输入键 key ,得到值 val + string name = hashmap.get(13276); + cout << "\n输入学号 13276 ,查询到姓名 " << name << endl; + + // 删除操作 + // 在哈希表中删除键值对 (key, val) + hashmap.remove(16750); + cout << "\n删除 16750 后,哈希表为\nKey -> Value" << endl; + hashmap.print(); + + return 0; +} diff --git a/chapter_hashing/simple_hash.cpp b/chapter_hashing/simple_hash.cpp new file mode 100644 index 0000000..bdb6c04 --- /dev/null +++ b/chapter_hashing/simple_hash.cpp @@ -0,0 +1,66 @@ +/** + * File: simple_hash.cpp + * Created Time: 2023-06-21 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ӷϣ */ +int addHash(string key) { + long long hash = 0; + const int MODULUS = 1000000007; + for (unsigned char c : key) { + hash = (hash + (int)c) % MODULUS; + } + return (int)hash; +} + +/* ˷ϣ */ +int mulHash(string key) { + long long hash = 0; + const int MODULUS = 1000000007; + for (unsigned char c : key) { + hash = (31 * hash + (int)c) % MODULUS; + } + return (int)hash; +} + +/* ϣ */ +int xorHash(string key) { + int hash = 0; + const int MODULUS = 1000000007; + for (unsigned char c : key) { + hash ^= (int)c; + } + return hash & MODULUS; +} + +/* תϣ */ +int rotHash(string key) { + long long hash = 0; + const int MODULUS = 1000000007; + for (unsigned char c : key) { + hash = ((hash << 4) ^ (hash >> 28) ^ (int)c) % MODULUS; + } + return (int)hash; +} + +/* Driver Code */ +int main() { + string key = "Hello dsad3241241dsa123"; + + int hash = addHash(key); + cout << "ӷϣֵΪ " << hash << endl; + + hash = mulHash(key); + cout << "˷ϣֵΪ " << hash << endl; + + hash = xorHash(key); + cout << "ϣֵΪ " << hash << endl; + + hash = rotHash(key); + cout << "תϣֵΪ " << hash << endl; + + return 0; +} diff --git a/chapter_heap/CMakeLists.txt b/chapter_heap/CMakeLists.txt new file mode 100644 index 0000000..1ac33a4 --- /dev/null +++ b/chapter_heap/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(heap heap.cpp) +add_executable(my_heap my_heap.cpp) +add_executable(top_k top_k.cpp) diff --git a/chapter_heap/heap.cpp b/chapter_heap/heap.cpp new file mode 100644 index 0000000..e50a451 --- /dev/null +++ b/chapter_heap/heap.cpp @@ -0,0 +1,66 @@ +/** + * File: heap.cpp + * Created Time: 2023-01-19 + * Author: LoneRanger(836253168@qq.com) + */ + +#include "../utils/common.hpp" + +void testPush(priority_queue &heap, int val) { + heap.push(val); // Ԫ + cout << "\nԪ " << val << " Ѻ" << endl; + printHeap(heap); +} + +void testPop(priority_queue &heap) { + int val = heap.top(); + heap.pop(); + cout << "\nѶԪ " << val << " Ѻ" << endl; + printHeap(heap); +} + +/* Driver Code */ +int main() { + /* ʼ */ + // ʼС + // priority_queue, greater> minHeap; + // ʼ󶥶 + priority_queue, less> maxHeap; + + cout << "\n²Ϊ󶥶" << endl; + + /* Ԫ */ + testPush(maxHeap, 1); + testPush(maxHeap, 3); + testPush(maxHeap, 2); + testPush(maxHeap, 5); + testPush(maxHeap, 4); + + /* ȡѶԪ */ + int peek = maxHeap.top(); + cout << "\nѶԪΪ " << peek << endl; + + /* ѶԪس */ + testPop(maxHeap); + testPop(maxHeap); + testPop(maxHeap); + testPop(maxHeap); + testPop(maxHeap); + + /* ȡѴС */ + int size = maxHeap.size(); + cout << "\nԪΪ " << size << endl; + + /* ж϶ǷΪ */ + bool isEmpty = maxHeap.empty(); + cout << "\nǷΪ " << isEmpty << endl; + + /* б */ + // ʱ临ӶΪ O(n) O(nlogn) + vector input{1, 3, 2, 5, 4}; + priority_queue, greater> minHeap(input.begin(), input.end()); + cout << "бСѺ" << endl; + printHeap(minHeap); + + return 0; +} diff --git a/chapter_heap/my_heap.cpp b/chapter_heap/my_heap.cpp new file mode 100644 index 0000000..9a3af17 --- /dev/null +++ b/chapter_heap/my_heap.cpp @@ -0,0 +1,155 @@ +/** + * File: my_heap.cpp + * Created Time: 2023-02-04 + * Author: LoneRanger (836253168@qq.com), what-is-me (whatisme@outlook.jp) + */ + +#include "../utils/common.hpp" + +/* 󶥶 */ +class MaxHeap { + private: + // ʹö̬飬뿼 + vector maxHeap; + + /* ȡӽڵ */ + int left(int i) { + return 2 * i + 1; + } + + /* ȡӽڵ */ + int right(int i) { + return 2 * i + 2; + } + + /* ȡڵ */ + int parent(int i) { + return (i - 1) / 2; // + } + + /* ӽڵ i ʼӵѻ */ + void siftUp(int i) { + while (true) { + // ȡڵ i ĸڵ + int p = parent(i); + // Խڵ㡱򡰽ڵ޸ʱѻ + if (p < 0 || maxHeap[i] <= maxHeap[p]) + break; + // ڵ + swap(maxHeap[i], maxHeap[p]); + // ѭ϶ѻ + i = p; + } + } + + /* ӽڵ i ʼӶ׶ѻ */ + void siftDown(int i) { + while (true) { + // жϽڵ i, l, r ֵĽڵ㣬Ϊ ma + int l = left(i), r = right(i), ma = i; + if (l < size() && maxHeap[l] > maxHeap[ma]) + ma = l; + if (r < size() && maxHeap[r] > maxHeap[ma]) + ma = r; + // ڵ i l, r Խ磬ѻ + if (ma == i) + break; + swap(maxHeap[i], maxHeap[ma]); + // ѭ¶ѻ + i = ma; + } + } + + public: + /* 췽б */ + MaxHeap(vector nums) { + // бԪԭⲻӽ + maxHeap = nums; + // ѻҶڵнڵ + for (int i = parent(size() - 1); i >= 0; i--) { + siftDown(i); + } + } + + /* ȡѴС */ + int size() { + return maxHeap.size(); + } + + /* ж϶ǷΪ */ + bool isEmpty() { + return size() == 0; + } + + /* ʶѶԪ */ + int peek() { + return maxHeap[0]; + } + + /* Ԫ */ + void push(int val) { + // ӽڵ + maxHeap.push_back(val); + // ӵѻ + siftUp(size() - 1); + } + + /* Ԫس */ + void pop() { + // пմ + if (isEmpty()) { + throw out_of_range("Ϊ"); + } + // ڵҶڵ㣨ԪβԪأ + swap(maxHeap[0], maxHeap[size() - 1]); + // ɾڵ + maxHeap.pop_back(); + // Ӷ׶ѻ + siftDown(0); + } + + /* ӡѣ*/ + void print() { + cout << "ѵʾ"; + printVector(maxHeap); + cout << "ѵ״ʾ" << endl; + TreeNode *root = vectorToTree(maxHeap); + printTree(root); + freeMemoryTree(root); + } +}; + +/* Driver Code */ +int main() { + /* ʼ󶥶 */ + vector vec{9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2}; + MaxHeap maxHeap(vec); + cout << "\nбѺ" << endl; + maxHeap.print(); + + /* ȡѶԪ */ + int peek = maxHeap.peek(); + cout << "\nѶԪΪ " << peek << endl; + + /* Ԫ */ + int val = 7; + maxHeap.push(val); + cout << "\nԪ " << val << " Ѻ" << endl; + maxHeap.print(); + + /* ѶԪس */ + peek = maxHeap.peek(); + maxHeap.pop(); + cout << "\nѶԪ " << peek << " Ѻ" << endl; + maxHeap.print(); + + /* ȡѴС */ + int size = maxHeap.size(); + cout << "\nԪΪ " << size << endl; + + /* ж϶ǷΪ */ + bool isEmpty = maxHeap.isEmpty(); + cout << "\nǷΪ " << isEmpty << endl; + + return 0; +} diff --git a/chapter_heap/top_k.cpp b/chapter_heap/top_k.cpp new file mode 100644 index 0000000..5c37ca7 --- /dev/null +++ b/chapter_heap/top_k.cpp @@ -0,0 +1,38 @@ +/** + * File: top_k.cpp + * Created Time: 2023-06-12 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ڶѲ k Ԫ */ +priority_queue, greater> topKHeap(vector &nums, int k) { + // ʼС + priority_queue, greater> heap; + // ǰ k Ԫ + for (int i = 0; i < k; i++) { + heap.push(nums[i]); + } + // ӵ k+1 ԪؿʼֶѵijΪ k + for (int i = k; i < nums.size(); i++) { + // ǰԪشڶѶԪأ򽫶ѶԪسѡǰԪ + if (nums[i] > heap.top()) { + heap.pop(); + heap.push(nums[i]); + } + } + return heap; +} + +// Driver Code +int main() { + vector nums = {1, 7, 6, 3, 2}; + int k = 3; + + priority_queue, greater> res = topKHeap(nums, k); + cout << " " << k << " ԪΪ: "; + printHeap(res); + + return 0; +} diff --git a/chapter_searching/CMakeLists.txt b/chapter_searching/CMakeLists.txt new file mode 100644 index 0000000..60a223d --- /dev/null +++ b/chapter_searching/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(binary_search binary_search.cpp) +add_executable(binary_search_insertion binary_search_insertion.cpp) +add_executable(binary_search_edge binary_search_edge.cpp) +add_executable(two_sum two_sum.cpp) diff --git a/chapter_searching/binary_search.cpp b/chapter_searching/binary_search.cpp new file mode 100644 index 0000000..e7056d3 --- /dev/null +++ b/chapter_searching/binary_search.cpp @@ -0,0 +1,59 @@ +/** + * File: binary_search.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ֲң˫䣩 */ +int binarySearch(vector &nums, int target) { + // ʼ˫ [0, n-1] i, j ֱָԪءβԪ + int i = 0, j = nums.size() - 1; + // ѭΪʱ i > j ʱΪգ + while (i <= j) { + int m = i + (j - i) / 2; // е m + if (nums[m] < target) // ˵ target [m+1, j] + i = m + 1; + else if (nums[m] > target) // ˵ target [i, m-1] + j = m - 1; + else // ҵĿԪأ + return m; + } + // δҵĿԪأ -1 + return -1; +} + +/* ֲңҿ䣩 */ +int binarySearchLCRO(vector &nums, int target) { + // ʼҿ [0, n) i, j ֱָԪءβԪ+1 + int i = 0, j = nums.size(); + // ѭΪʱ i = j ʱΪգ + while (i < j) { + int m = i + (j - i) / 2; // е m + if (nums[m] < target) // ˵ target [m+1, j) + i = m + 1; + else if (nums[m] > target) // ˵ target [i, m) + j = m; + else // ҵĿԪأ + return m; + } + // δҵĿԪأ -1 + return -1; +} + +/* Driver Code */ +int main() { + int target = 6; + vector nums = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35}; + + /* ֲң˫䣩 */ + int index = binarySearch(nums, target); + cout << "ĿԪ 6 = " << index << endl; + + /* ֲңҿ䣩 */ + index = binarySearchLCRO(nums, target); + cout << "ĿԪ 6 = " << index << endl; + + return 0; +} diff --git a/chapter_searching/binary_search_edge.cpp b/chapter_searching/binary_search_edge.cpp new file mode 100644 index 0000000..7b9a30f --- /dev/null +++ b/chapter_searching/binary_search_edge.cpp @@ -0,0 +1,66 @@ +/** + * File: binary_search_edge.cpp + * Created Time: 2023-08-04 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ֲҲ㣨ظԪأ */ +int binarySearchInsertion(const vector &nums, int target) { + int i = 0, j = nums.size() - 1; // ʼ˫ [0, n-1] + while (i <= j) { + int m = i + (j - i) / 2; // е m + if (nums[m] < target) { + i = m + 1; // target [m+1, j] + } else { + j = m - 1; // ׸С target Ԫ [i, m-1] + } + } + // ز i + return i; +} + +/* ֲһ target */ +int binarySearchLeftEdge(vector &nums, int target) { + // ȼڲ target IJ + int i = binarySearchInsertion(nums, target); + // δҵ target -1 + if (i == nums.size() || nums[i] != target) { + return -1; + } + // ҵ target i + return i; +} + +/* ֲһ target */ +int binarySearchRightEdge(vector &nums, int target) { + // תΪһ target + 1 + int i = binarySearchInsertion(nums, target + 1); + // j ָһ target i ָ׸ target Ԫ + int j = i - 1; + // δҵ target -1 + if (j == -1 || nums[j] != target) { + return -1; + } + // ҵ target j + return j; +} + +/* Driver Code */ +int main() { + // ظԪص + vector nums = {1, 3, 6, 6, 6, 6, 6, 10, 12, 15}; + cout << "\n nums = "; + printVector(nums); + + // ֲ߽ұ߽ + for (int target : {6, 7}) { + int index = binarySearchLeftEdge(nums, target); + cout << "һԪ " << target << " Ϊ " << index << endl; + index = binarySearchRightEdge(nums, target); + cout << "һԪ " << target << " Ϊ " << index << endl; + } + + return 0; +} diff --git a/chapter_searching/binary_search_insertion.cpp b/chapter_searching/binary_search_insertion.cpp new file mode 100644 index 0000000..384fd92 --- /dev/null +++ b/chapter_searching/binary_search_insertion.cpp @@ -0,0 +1,66 @@ +/** + * File: binary_search_insertion.cpp + * Created Time: 2023-08-04 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ֲҲ㣨ظԪأ */ +int binarySearchInsertionSimple(vector &nums, int target) { + int i = 0, j = nums.size() - 1; // ʼ˫ [0, n-1] + while (i <= j) { + int m = i + (j - i) / 2; // е m + if (nums[m] < target) { + i = m + 1; // target [m+1, j] + } else if (nums[m] > target) { + j = m - 1; // target [i, m-1] + } else { + return m; // ҵ target ز m + } + } + // δҵ target ز i + return i; +} + +/* ֲҲ㣨ظԪأ */ +int binarySearchInsertion(vector &nums, int target) { + int i = 0, j = nums.size() - 1; // ʼ˫ [0, n-1] + while (i <= j) { + int m = i + (j - i) / 2; // е m + if (nums[m] < target) { + i = m + 1; // target [m+1, j] + } else if (nums[m] > target) { + j = m - 1; // target [i, m-1] + } else { + j = m - 1; // ׸С target Ԫ [i, m-1] + } + } + // ز i + return i; +} + +/* Driver Code */ +int main() { + // ظԪص + vector nums = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35}; + cout << "\n nums = "; + printVector(nums); + // ֲҲ + for (int target : {6, 9}) { + int index = binarySearchInsertionSimple(nums, target); + cout << "Ԫ " << target << " IJΪ " << index << endl; + } + + // ظԪص + nums = {1, 3, 6, 6, 6, 6, 6, 10, 12, 15}; + cout << "\n nums = "; + printVector(nums); + // ֲҲ + for (int target : {2, 6, 20}) { + int index = binarySearchInsertion(nums, target); + cout << "Ԫ " << target << " IJΪ " << index << endl; + } + + return 0; +} diff --git a/chapter_searching/hashing_search.cpp b/chapter_searching/hashing_search.cpp new file mode 100644 index 0000000..31a895d --- /dev/null +++ b/chapter_searching/hashing_search.cpp @@ -0,0 +1,53 @@ +/** + * File: hashing_search.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ϣң飩 */ +int hashingSearchArray(unordered_map map, int target) { + // ϣ key: ĿԪأvalue: + // ϣ޴ key -1 + if (map.find(target) == map.end()) + return -1; + return map[target]; +} + +/* ϣң */ +ListNode *hashingSearchLinkedList(unordered_map map, int target) { + // ϣ key: Ŀڵֵvalue: ڵ + // ϣ޴ key nullptr + if (map.find(target) == map.end()) + return nullptr; + return map[target]; +} + +/* Driver Code */ +int main() { + int target = 3; + + /* ϣң飩 */ + vector nums = {1, 5, 3, 2, 4, 7, 5, 9, 10, 8}; + // ʼϣ + unordered_map map; + for (int i = 0; i < nums.size(); i++) { + map[nums[i]] = i; // key: Ԫأvalue: + } + int index = hashingSearchArray(map, target); + cout << "ĿԪ 3 = " << index << endl; + + /* ϣң */ + ListNode *head = vecToLinkedList(nums); + // ʼϣ + unordered_map map1; + while (head != nullptr) { + map1[head->val] = head; // key: ڵֵvalue: ڵ + head = head->next; + } + ListNode *node = hashingSearchLinkedList(map1, target); + cout << "Ŀڵֵ 3 ĶӦڵΪ " << node << endl; + + return 0; +} diff --git a/chapter_searching/linear_search.cpp b/chapter_searching/linear_search.cpp new file mode 100644 index 0000000..c88af6f --- /dev/null +++ b/chapter_searching/linear_search.cpp @@ -0,0 +1,49 @@ +/** + * File: linear_search.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Բң飩 */ +int linearSearchArray(vector &nums, int target) { + // + for (int i = 0; i < nums.size(); i++) { + // ҵĿԪأ + if (nums[i] == target) + return i; + } + // δҵĿԪأ -1 + return -1; +} + +/* Բң */ +ListNode *linearSearchLinkedList(ListNode *head, int target) { + // + while (head != nullptr) { + // ҵĿڵ㣬֮ + if (head->val == target) + return head; + head = head->next; + } + // δҵĿڵ㣬 nullptr + return nullptr; +} + +/* Driver Code */ +int main() { + int target = 3; + + /* ִԲ */ + vector nums = {1, 5, 3, 2, 4, 7, 5, 9, 10, 8}; + int index = linearSearchArray(nums, target); + cout << "ĿԪ 3 = " << index << endl; + + /* ִԲ */ + ListNode *head = vecToLinkedList(nums); + ListNode *node = linearSearchLinkedList(head, target); + cout << "Ŀڵֵ 3 ĶӦڵΪ " << node << endl; + + return 0; +} diff --git a/chapter_searching/two_sum.cpp b/chapter_searching/two_sum.cpp new file mode 100644 index 0000000..5ff81d0 --- /dev/null +++ b/chapter_searching/two_sum.cpp @@ -0,0 +1,54 @@ +/** + * File: two_sum.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* һö */ +vector twoSumBruteForce(vector &nums, int target) { + int size = nums.size(); + // ѭʱ临ӶΪ O(n^2) + for (int i = 0; i < size - 1; i++) { + for (int j = i + 1; j < size; j++) { + if (nums[i] + nums[j] == target) + return {i, j}; + } + } + return {}; +} + +/* ϣ */ +vector twoSumHashTable(vector &nums, int target) { + int size = nums.size(); + // ϣռ临ӶΪ O(n) + unordered_map dic; + // ѭʱ临ӶΪ O(n) + for (int i = 0; i < size; i++) { + if (dic.find(target - nums[i]) != dic.end()) { + return {dic[target - nums[i]], i}; + } + dic.emplace(nums[i], i); + } + return {}; +} + +/* Driver Code */ +int main() { + // ======= Test Case ======= + vector nums = {2, 7, 11, 15}; + int target = 13; + + // ====== Driver Code ====== + // һ + vector res = twoSumBruteForce(nums, target); + cout << "һ res = "; + printVector(res); + // + res = twoSumHashTable(nums, target); + cout << " res = "; + printVector(res); + + return 0; +} diff --git a/chapter_sorting/CMakeLists.txt b/chapter_sorting/CMakeLists.txt new file mode 100644 index 0000000..e6347cf --- /dev/null +++ b/chapter_sorting/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(selection_sort selection_sort.cpp) +add_executable(bubble_sort bubble_sort.cpp) +add_executable(insertion_sort insertion_sort.cpp) +add_executable(merge_sort merge_sort.cpp) +add_executable(quick_sort quick_sort.cpp) +add_executable(heap_sort heap_sort.cpp) \ No newline at end of file diff --git a/chapter_sorting/bubble_sort.cpp b/chapter_sorting/bubble_sort.cpp new file mode 100644 index 0000000..2ddf2a7 --- /dev/null +++ b/chapter_sorting/bubble_sort.cpp @@ -0,0 +1,56 @@ +/** + * File: bubble_sort.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ð */ +void bubbleSort(vector &nums) { + // ѭδΪ [0, i] + for (int i = nums.size() - 1; i > 0; i--) { + // ѭδ [0, i] еԪؽҶ + for (int j = 0; j < i; j++) { + if (nums[j] > nums[j + 1]) { + // nums[j] nums[j + 1] + // ʹ std::swap() + swap(nums[j], nums[j + 1]); + } + } + } +} + +/* ð򣨱־Ż*/ +void bubbleSortWithFlag(vector &nums) { + // ѭδΪ [0, i] + for (int i = nums.size() - 1; i > 0; i--) { + bool flag = false; // ʼ־λ + // ѭδ [0, i] еԪؽҶ + for (int j = 0; j < i; j++) { + if (nums[j] > nums[j + 1]) { + // nums[j] nums[j + 1] + // ʹ std::swap() + swap(nums[j], nums[j + 1]); + flag = true; // ¼Ԫ + } + } + if (!flag) + break; // ֡ðݡδκԪأֱ + } +} + +/* Driver Code */ +int main() { + vector nums = {4, 1, 3, 1, 5, 2}; + bubbleSort(nums); + cout << "ðɺ nums = "; + printVector(nums); + + vector nums1 = {4, 1, 3, 1, 5, 2}; + bubbleSortWithFlag(nums1); + cout << "ðɺ nums1 = "; + printVector(nums1); + + return 0; +} diff --git a/chapter_sorting/bucket_sort.cpp b/chapter_sorting/bucket_sort.cpp new file mode 100644 index 0000000..c5ffd5e --- /dev/null +++ b/chapter_sorting/bucket_sort.cpp @@ -0,0 +1,44 @@ +/** + * File: bucket_sort.cpp + * Created Time: 2023-03-30 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Ͱ */ +void bucketSort(vector &nums) { + // ʼ k = n/2 ͰԤÿͰ 2 Ԫ + int k = nums.size() / 2; + vector> buckets(k); + // 1. Ԫط䵽Ͱ + for (float num : nums) { + // ݷΧΪ [0, 1)ʹ num * k ӳ䵽Χ [0, k-1] + int i = num * k; + // num ӽͰ bucket_idx + buckets[i].push_back(num); + } + // 2. ԸͰִ + for (vector &bucket : buckets) { + // ʹҲ滻㷨 + sort(bucket.begin(), bucket.end()); + } + // 3. Ͱϲ + int i = 0; + for (vector &bucket : buckets) { + for (float num : bucket) { + nums[i++] = num; + } + } +} + +/* Driver Code */ +int main() { + // ΪΧΪ [0, 1) + vector nums = {0.49f, 0.96f, 0.82f, 0.09f, 0.57f, 0.43f, 0.91f, 0.75f, 0.15f, 0.37f}; + bucketSort(nums); + cout << "Ͱɺ nums = "; + printVector(nums); + + return 0; +} diff --git a/chapter_sorting/counting_sort.cpp b/chapter_sorting/counting_sort.cpp new file mode 100644 index 0000000..bbc5948 --- /dev/null +++ b/chapter_sorting/counting_sort.cpp @@ -0,0 +1,77 @@ +/** + * File: counting_sort.cpp + * Created Time: 2023-03-17 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +// ʵ֣޷ +void countingSortNaive(vector &nums) { + // 1. ͳԪ m + int m = 0; + for (int num : nums) { + m = max(m, num); + } + // 2. ͳƸֵijִ + // counter[num] num ijִ + vector counter(m + 1, 0); + for (int num : nums) { + counter[num]++; + } + // 3. counter Ԫԭ nums + int i = 0; + for (int num = 0; num < m + 1; num++) { + for (int j = 0; j < counter[num]; j++, i++) { + nums[i] = num; + } + } +} + +/* */ +// ʵ֣󣬲ȶ +void countingSort(vector &nums) { + // 1. ͳԪ m + int m = 0; + for (int num : nums) { + m = max(m, num); + } + // 2. ͳƸֵijִ + // counter[num] num ijִ + vector counter(m + 1, 0); + for (int num : nums) { + counter[num]++; + } + // 3. counter ǰ׺ִͣתΪβ + // counter[num]-1 num res һγֵ + for (int i = 0; i < m; i++) { + counter[i + 1] += counter[i]; + } + // 4. nums Ԫ res + // ʼ res ڼ¼ + int n = nums.size(); + vector res(n); + for (int i = n - 1; i >= 0; i--) { + int num = nums[i]; + res[counter[num] - 1] = num; // num õӦ + counter[num]--; // ǰ׺Լ 1 õ´η num + } + // ʹý res ԭ nums + nums = res; +} + +/* Driver Code */ +int main() { + vector nums = {1, 0, 1, 2, 0, 4, 0, 2, 2, 4}; + countingSortNaive(nums); + cout << "޷ɺ nums = "; + printVector(nums); + + vector nums1 = {1, 0, 1, 2, 0, 4, 0, 2, 2, 4}; + countingSort(nums1); + cout << "ɺ nums1 = "; + printVector(nums1); + + return 0; +} diff --git a/chapter_sorting/heap_sort.cpp b/chapter_sorting/heap_sort.cpp new file mode 100644 index 0000000..a724f47 --- /dev/null +++ b/chapter_sorting/heap_sort.cpp @@ -0,0 +1,54 @@ +/** + * File: heap_sort.cpp + * Created Time: 2023-05-26 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ѵijΪ n ӽڵ i ʼӶ׶ѻ */ +void siftDown(vector &nums, int n, int i) { + while (true) { + // жϽڵ i, l, r ֵĽڵ㣬Ϊ ma + int l = 2 * i + 1; + int r = 2 * i + 2; + int ma = i; + if (l < n && nums[l] > nums[ma]) + ma = l; + if (r < n && nums[r] > nums[ma]) + ma = r; + // ڵ i l, r Խ磬ѻ + if (ma == i) { + break; + } + // ڵ + swap(nums[i], nums[ma]); + // ѭ¶ѻ + i = ma; + } +} + +/* */ +void heapSort(vector &nums) { + // ѲѻҶڵнڵ + for (int i = nums.size() / 2 - 1; i >= 0; --i) { + siftDown(nums, nums.size(), i); + } + // ӶȡԪأѭ n-1 + for (int i = nums.size() - 1; i > 0; --i) { + // ڵҶڵ㣨ԪβԪأ + swap(nums[0], nums[i]); + // ԸڵΪ㣬Ӷ׽жѻ + siftDown(nums, i, 0); + } +} + +/* Driver Code */ +int main() { + vector nums = {4, 1, 3, 1, 5, 2}; + heapSort(nums); + cout << "ɺ nums = "; + printVector(nums); + + return 0; +} diff --git a/chapter_sorting/insertion_sort.cpp b/chapter_sorting/insertion_sort.cpp new file mode 100644 index 0000000..d602ee4 --- /dev/null +++ b/chapter_sorting/insertion_sort.cpp @@ -0,0 +1,31 @@ +/** + * File: insertion_sort.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +void insertionSort(vector &nums) { + // ѭԪΪ 1, 2, ..., n + for (int i = 1; i < nums.size(); i++) { + int base = nums[i], j = i - 1; + // ѭ base 뵽򲿷ֵȷλ + while (j >= 0 && nums[j] > base) { + nums[j + 1] = nums[j]; // nums[j] ƶһλ + j--; + } + nums[j + 1] = base; // base ֵȷλ + } +} + +/* Driver Code */ +int main() { + vector nums = {4, 1, 3, 1, 5, 2}; + insertionSort(nums); + cout << "ɺ nums = "; + printVector(nums); + + return 0; +} diff --git a/chapter_sorting/merge_sort.cpp b/chapter_sorting/merge_sort.cpp new file mode 100644 index 0000000..56e71c2 --- /dev/null +++ b/chapter_sorting/merge_sort.cpp @@ -0,0 +1,58 @@ +/** + * File: merge_sort.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ϲ */ +void merge(vector &nums, int left, int mid, int right) { + // Ϊ [left, mid], Ϊ [mid+1, right] + // һʱ tmp ڴźϲĽ + vector tmp(right - left + 1); + // ʼʼ + int i = left, j = mid + 1, k = 0; + // 鶼ԪʱбȽϲСԪظƵʱ + while (i <= mid && j <= right) { + if (nums[i] <= nums[j]) + tmp[k++] = nums[i++]; + else + tmp[k++] = nums[j++]; + } + // ʣԪظƵʱ + while (i <= mid) { + tmp[k++] = nums[i++]; + } + while (j <= right) { + tmp[k++] = nums[j++]; + } + // ʱ tmp еԪظƻԭ nums ĶӦ + for (k = 0; k < tmp.size(); k++) { + nums[left + k] = tmp[k]; + } +} + +/* 鲢 */ +void mergeSort(vector &nums, int left, int right) { + // ֹ + if (left >= right) + return; // 鳤Ϊ 1 ʱֹݹ + // ֽ׶ + int mid = (left + right) / 2; // е + mergeSort(nums, left, mid); // ݹ + mergeSort(nums, mid + 1, right); // ݹ + // ϲ׶ + merge(nums, left, mid, right); +} + +/* Driver Code */ +int main() { + /* 鲢 */ + vector nums = {7, 3, 2, 6, 0, 1, 5, 4}; + mergeSort(nums, 0, nums.size() - 1); + cout << "鲢ɺ nums = "; + printVector(nums); + + return 0; +} diff --git a/chapter_sorting/quick_sort.cpp b/chapter_sorting/quick_sort.cpp new file mode 100644 index 0000000..4e3d390 --- /dev/null +++ b/chapter_sorting/quick_sort.cpp @@ -0,0 +1,168 @@ +/** + * File: quick_sort.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +class QuickSort { + private: + /* Ԫؽ */ + static void swap(vector &nums, int i, int j) { + int tmp = nums[i]; + nums[i] = nums[j]; + nums[j] = tmp; + } + + /* ڱ */ + static int partition(vector &nums, int left, int right) { + // nums[left] Ϊ׼ + int i = left, j = right; + while (i < j) { + while (i < j && nums[j] >= nums[left]) + j--; // ׸Сڻ׼Ԫ + while (i < j && nums[i] <= nums[left]) + i++; // ׸ڻ׼Ԫ + swap(nums, i, j); // Ԫ + } + swap(nums, i, left); // ׼ķֽ + return i; // ػ׼ + } + + public: + /* */ + static void quickSort(vector &nums, int left, int right) { + // 鳤Ϊ 1 ʱֹݹ + if (left >= right) + return; + // ڱ + int pivot = partition(nums, left, right); + // ݹ顢 + quickSort(nums, left, pivot - 1); + quickSort(nums, pivot + 1, right); + } +}; + +/* ࣨλ׼Ż */ +class QuickSortMedian { + private: + /* Ԫؽ */ + static void swap(vector &nums, int i, int j) { + int tmp = nums[i]; + nums[i] = nums[j]; + nums[j] = tmp; + } + + /* ѡȡѡԪصλ */ + static int medianThree(vector &nums, int left, int mid, int right) { + // ˴ʹ򻯴 + // Ϊ 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1 + if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right])) + return left; + else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right])) + return mid; + else + return right; + } + + /* ڱ֣ȡֵ */ + static int partition(vector &nums, int left, int right) { + // ѡȡѡԪصλ + int med = medianThree(nums, left, (left + right) / 2, right); + // λ + swap(nums, left, med); + // nums[left] Ϊ׼ + int i = left, j = right; + while (i < j) { + while (i < j && nums[j] >= nums[left]) + j--; // ׸Сڻ׼Ԫ + while (i < j && nums[i] <= nums[left]) + i++; // ׸ڻ׼Ԫ + swap(nums, i, j); // Ԫ + } + swap(nums, i, left); // ׼ķֽ + return i; // ػ׼ + } + + public: + /* */ + static void quickSort(vector &nums, int left, int right) { + // 鳤Ϊ 1 ʱֹݹ + if (left >= right) + return; + // ڱ + int pivot = partition(nums, left, right); + // ݹ顢 + quickSort(nums, left, pivot - 1); + quickSort(nums, pivot + 1, right); + } +}; + +/* ࣨβݹŻ */ +class QuickSortTailCall { + private: + /* Ԫؽ */ + static void swap(vector &nums, int i, int j) { + int tmp = nums[i]; + nums[i] = nums[j]; + nums[j] = tmp; + } + + /* ڱ */ + static int partition(vector &nums, int left, int right) { + // nums[left] Ϊ׼ + int i = left, j = right; + while (i < j) { + while (i < j && nums[j] >= nums[left]) + j--; // ׸Сڻ׼Ԫ + while (i < j && nums[i] <= nums[left]) + i++; // ׸ڻ׼Ԫ + swap(nums, i, j); // Ԫ + } + swap(nums, i, left); // ׼ķֽ + return i; // ػ׼ + } + + public: + /* βݹŻ */ + static void quickSort(vector &nums, int left, int right) { + // 鳤Ϊ 1 ʱֹ + while (left < right) { + // ڱֲ + int pivot = partition(nums, left, right); + // н϶̵Ǹִп + if (pivot - left < right - pivot) { + quickSort(nums, left, pivot - 1); // ݹ + left = pivot + 1; // ʣδΪ [pivot + 1, right] + } else { + quickSort(nums, pivot + 1, right); // ݹ + right = pivot - 1; // ʣδΪ [left, pivot - 1] + } + } + } +}; + +/* Driver Code */ +int main() { + /* */ + vector nums{2, 4, 1, 0, 3, 5}; + QuickSort::quickSort(nums, 0, nums.size() - 1); + cout << "ɺ nums = "; + printVector(nums); + + /* λ׼Ż */ + vector nums1 = {2, 4, 1, 0, 3, 5}; + QuickSortMedian::quickSort(nums1, 0, nums1.size() - 1); + cout << "λ׼Żɺ nums = "; + printVector(nums); + + /* βݹŻ */ + vector nums2 = {2, 4, 1, 0, 3, 5}; + QuickSortTailCall::quickSort(nums2, 0, nums2.size() - 1); + cout << "βݹŻɺ nums = "; + printVector(nums); + + return 0; +} diff --git a/chapter_sorting/radix_sort.cpp b/chapter_sorting/radix_sort.cpp new file mode 100644 index 0000000..c4d8cf4 --- /dev/null +++ b/chapter_sorting/radix_sort.cpp @@ -0,0 +1,65 @@ +/** + * File: radix_sort.cpp + * Created Time: 2023-03-26 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ȡԪ num ĵ k λ exp = 10^(k-1) */ +int digit(int num, int exp) { + // exp k ԱڴظִаĴη + return (num / exp) % 10; +} + +/* 򣨸 nums k λ */ +void countingSortDigit(vector &nums, int exp) { + // ʮƵλΧΪ 0~9 ҪΪ 10 Ͱ + vector counter(10, 0); + int n = nums.size(); + // ͳ 0~9 ֵijִ + for (int i = 0; i < n; i++) { + int d = digit(nums[i], exp); // ȡ nums[i] k λΪ d + counter[d]++; // ͳ d ijִ + } + // ǰ׺ָͣתΪ + for (int i = 1; i < 10; i++) { + counter[i] += counter[i - 1]; + } + // ͰͳƽԪ res + vector res(n, 0); + for (int i = n - 1; i >= 0; i--) { + int d = digit(nums[i], exp); + int j = counter[d] - 1; // ȡ d е j + res[j] = nums[i]; // ǰԪ j + counter[d]--; // d 1 + } + // ʹýԭ nums + for (int i = 0; i < n; i++) + nums[i] = res[i]; +} + +/* */ +void radixSort(vector &nums) { + // ȡԪأжλ + int m = *max_element(nums.begin(), nums.end()); + // մӵλλ˳ + for (int exp = 1; exp <= m; exp *= 10) + // Ԫصĵ k λִм + // k = 1 -> exp = 1 + // k = 2 -> exp = 10 + // exp = 10^(k-1) + countingSortDigit(nums, exp); +} + +/* Driver Code */ +int main() { + // + vector nums = {10546151, 35663510, 42865989, 34862445, 81883077, + 88906420, 72429244, 30524779, 82060337, 63832996}; + radixSort(nums); + cout << "ɺ nums = "; + printVector(nums); + + return 0; +} diff --git a/chapter_sorting/selection_sort.cpp b/chapter_sorting/selection_sort.cpp new file mode 100644 index 0000000..25899e7 --- /dev/null +++ b/chapter_sorting/selection_sort.cpp @@ -0,0 +1,34 @@ +/** + * File: selection_sort.cpp + * Created Time: 2023-05-23 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ѡ */ +void selectionSort(vector &nums) { + int n = nums.size(); + // ѭδΪ [i, n-1] + for (int i = 0; i < n - 1; i++) { + // ѭҵδڵСԪ + int k = i; + for (int j = i + 1; j < n; j++) { + if (nums[j] < nums[k]) + k = j; // ¼СԪص + } + // СԪδ׸Ԫؽ + swap(nums[i], nums[k]); + } +} + +/* Driver Code */ +int main() { + vector nums = {4, 1, 3, 1, 5, 2}; + selectionSort(nums); + + cout << "ѡɺ nums = "; + printVector(nums); + + return 0; +} diff --git a/chapter_stack_and_queue/CMakeLists.txt b/chapter_stack_and_queue/CMakeLists.txt new file mode 100644 index 0000000..b55878a --- /dev/null +++ b/chapter_stack_and_queue/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(array_deque array_deque.cpp) +add_executable(array_queue array_queue.cpp) +add_executable(array_stack array_stack.cpp) +add_executable(deque deque.cpp) +add_executable(linkedlist_deque linkedlist_deque.cpp) +add_executable(linkedlist_queue linkedlist_queue.cpp) +add_executable(linkedlist_stack linkedlist_stack.cpp) +add_executable(queue queue.cpp) +add_executable(stack stack.cpp) diff --git a/chapter_stack_and_queue/array_deque.cpp b/chapter_stack_and_queue/array_deque.cpp new file mode 100644 index 0000000..8c83296 --- /dev/null +++ b/chapter_stack_and_queue/array_deque.cpp @@ -0,0 +1,156 @@ +/** + * File: array_deque.cpp + * Created Time: 2023-03-02 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ڻʵֵ˫ */ +class ArrayDeque { + private: + vector nums; // ڴ洢˫Ԫص + int front; // ָ룬ָԪ + int queSize; // ˫г + + public: + /* 췽 */ + ArrayDeque(int capacity) { + nums.resize(capacity); + front = queSize = 0; + } + + /* ȡ˫е */ + int capacity() { + return nums.size(); + } + + /* ȡ˫еij */ + int size() { + return queSize; + } + + /* ж˫ǷΪ */ + bool isEmpty() { + return queSize == 0; + } + + /* 㻷 */ + int index(int i) { + // ͨȡʵβ + // i Խβ󣬻صͷ + // i Խͷ󣬻صβ + return (i + capacity()) % capacity(); + } + + /* */ + void pushFirst(int num) { + if (queSize == capacity()) { + cout << "˫" << endl; + return; + } + // ָƶһλ + // ͨȡʵ front Խͷصβ + front = index(front - 1); + // num + nums[front] = num; + queSize++; + } + + /* β */ + void pushLast(int num) { + if (queSize == capacity()) { + cout << "˫" << endl; + return; + } + // βָ룬ָβ + 1 + int rear = index(front + queSize); + // num β + nums[rear] = num; + queSize++; + } + + /* ׳ */ + int popFirst() { + int num = peekFirst(); + // ָƶһλ + front = index(front + 1); + queSize--; + return num; + } + + /* β */ + int popLast() { + int num = peekLast(); + queSize--; + return num; + } + + /* ʶԪ */ + int peekFirst() { + if (isEmpty()) + throw out_of_range("˫Ϊ"); + return nums[front]; + } + + /* ʶβԪ */ + int peekLast() { + if (isEmpty()) + throw out_of_range("˫Ϊ"); + // βԪ + int last = index(front + queSize - 1); + return nums[last]; + } + + /* ڴӡ */ + vector toVector() { + // תЧȷΧڵбԪ + vector res(queSize); + for (int i = 0, j = front; i < queSize; i++, j++) { + res[i] = nums[index(j)]; + } + return res; + } +}; + +/* Driver Code */ +int main() { + /* ʼ˫ */ + ArrayDeque *deque = new ArrayDeque(10); + deque->pushLast(3); + deque->pushLast(2); + deque->pushLast(5); + cout << "˫ deque = "; + printVector(deque->toVector()); + + /* Ԫ */ + int peekFirst = deque->peekFirst(); + cout << "Ԫ peekFirst = " << peekFirst << endl; + int peekLast = deque->peekLast(); + cout << "βԪ peekLast = " << peekLast << endl; + + /* Ԫ */ + deque->pushLast(4); + cout << "Ԫ 4 βӺ deque = "; + printVector(deque->toVector()); + deque->pushFirst(1); + cout << "Ԫ 1 Ӻ deque = "; + printVector(deque->toVector()); + + /* Ԫس */ + int popLast = deque->popLast(); + cout << "βԪ = " << popLast << "βӺ deque = "; + printVector(deque->toVector()); + int popFirst = deque->popFirst(); + cout << "׳Ԫ = " << popFirst << "׳Ӻ deque = "; + printVector(deque->toVector()); + + /* ȡ˫еij */ + int size = deque->size(); + cout << "˫г size = " << size << endl; + + /* ж˫ǷΪ */ + bool isEmpty = deque->isEmpty(); + cout << "˫ǷΪ = " << boolalpha << isEmpty << endl; + return 0; +} diff --git a/chapter_stack_and_queue/array_queue.cpp b/chapter_stack_and_queue/array_queue.cpp new file mode 100644 index 0000000..282d42a --- /dev/null +++ b/chapter_stack_and_queue/array_queue.cpp @@ -0,0 +1,129 @@ +/** + * File: array_queue.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ڻʵֵĶ */ +class ArrayQueue { + private: + int *nums; // ڴ洢Ԫص + int front; // ָ룬ָԪ + int queSize; // г + int queCapacity; // + + public: + ArrayQueue(int capacity) { + // ʼ + nums = new int[capacity]; + queCapacity = capacity; + front = queSize = 0; + } + + ~ArrayQueue() { + delete[] nums; + } + + /* ȡе */ + int capacity() { + return queCapacity; + } + + /* ȡеij */ + int size() { + return queSize; + } + + /* ж϶ǷΪ */ + bool isEmpty() { + return size() == 0; + } + + /* */ + void push(int num) { + if (queSize == queCapacity) { + cout << "" << endl; + return; + } + // βָ룬ָβ + 1 + // ͨȡʵ rear Խβصͷ + int rear = (front + queSize) % queCapacity; + // num β + nums[rear] = num; + queSize++; + } + + /* */ + int pop() { + int num = peek(); + // ָƶһλԽβ򷵻صͷ + front = (front + 1) % queCapacity; + queSize--; + return num; + } + + /* ʶԪ */ + int peek() { + if (isEmpty()) + throw out_of_range("Ϊ"); + return nums[front]; + } + + /* תΪ Vector */ + vector toVector() { + // תЧȷΧڵбԪ + vector arr(queSize); + for (int i = 0, j = front; i < queSize; i++, j++) { + arr[i] = nums[j % queCapacity]; + } + return arr; + } +}; + +/* Driver Code */ +int main() { + /* ʼ */ + int capacity = 10; + ArrayQueue *queue = new ArrayQueue(capacity); + + /* Ԫ */ + queue->push(1); + queue->push(3); + queue->push(2); + queue->push(5); + queue->push(4); + cout << " queue = "; + printVector(queue->toVector()); + + /* ʶԪ */ + int peek = queue->peek(); + cout << "Ԫ peek = " << peek << endl; + + /* Ԫس */ + peek = queue->pop(); + cout << "Ԫ pop = " << peek << "Ӻ queue = "; + printVector(queue->toVector()); + + /* ȡеij */ + int size = queue->size(); + cout << "г size = " << size << endl; + + /* ж϶ǷΪ */ + bool empty = queue->isEmpty(); + cout << "ǷΪ = " << empty << endl; + + /* Ի */ + for (int i = 0; i < 10; i++) { + queue->push(i); + queue->pop(); + cout << " " << i << " + Ӻ queue = "; + printVector(queue->toVector()); + } + + // ͷڴ + delete queue; + + return 0; +} diff --git a/chapter_stack_and_queue/array_stack.cpp b/chapter_stack_and_queue/array_stack.cpp new file mode 100644 index 0000000..b68b2f5 --- /dev/null +++ b/chapter_stack_and_queue/array_stack.cpp @@ -0,0 +1,85 @@ +/** + * File: array_stack.cpp + * Created Time: 2022-11-28 + * Author: qualifier1024 (2539244001@qq.com) + */ + +#include "../utils/common.hpp" + +/* ʵֵջ */ +class ArrayStack { + private: + vector stack; + + public: + /* ȡջij */ + int size() { + return stack.size(); + } + + /* жջǷΪ */ + bool isEmpty() { + return stack.size() == 0; + } + + /* ջ */ + void push(int num) { + stack.push_back(num); + } + + /* ջ */ + int pop() { + int num = top(); + stack.pop_back(); + return num; + } + + /* ջԪ */ + int top() { + if (isEmpty()) + throw out_of_range("ջΪ"); + return stack.back(); + } + + /* Vector */ + vector toVector() { + return stack; + } +}; + +/* Driver Code */ +int main() { + /* ʼջ */ + ArrayStack *stack = new ArrayStack(); + + /* Ԫջ */ + stack->push(1); + stack->push(3); + stack->push(2); + stack->push(5); + stack->push(4); + cout << "ջ stack = "; + printVector(stack->toVector()); + + /* ջԪ */ + int top = stack->top(); + cout << "ջԪ top = " << top << endl; + + /* Ԫسջ */ + top = stack->pop(); + cout << "ջԪ pop = " << top << "ջ stack = "; + printVector(stack->toVector()); + + /* ȡջij */ + int size = stack->size(); + cout << "ջij size = " << size << endl; + + /* жǷΪ */ + bool empty = stack->isEmpty(); + cout << "ջǷΪ = " << empty << endl; + + // ͷڴ + delete stack; + + return 0; +} diff --git a/chapter_stack_and_queue/deque.cpp b/chapter_stack_and_queue/deque.cpp new file mode 100644 index 0000000..73da7b3 --- /dev/null +++ b/chapter_stack_and_queue/deque.cpp @@ -0,0 +1,46 @@ +/** + * File: deque.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Driver Code */ +int main() { + /* ʼ˫ */ + deque deque; + + /* Ԫ */ + deque.push_back(2); + deque.push_back(5); + deque.push_back(4); + deque.push_front(3); + deque.push_front(1); + cout << "˫ deque = "; + printDeque(deque); + + /* Ԫ */ + int front = deque.front(); + cout << "Ԫ front = " << front << endl; + int back = deque.back(); + cout << "βԪ back = " << back << endl; + + /* Ԫس */ + deque.pop_front(); + cout << "׳Ԫ popFront = " << front << "׳Ӻ deque = "; + printDeque(deque); + deque.pop_back(); + cout << "βԪ popLast = " << back << "βӺ deque = "; + printDeque(deque); + + /* ȡ˫еij */ + int size = deque.size(); + cout << "˫г size = " << size << endl; + + /* ж˫ǷΪ */ + bool empty = deque.empty(); + cout << "˫ǷΪ = " << empty << endl; + + return 0; +} diff --git a/chapter_stack_and_queue/linkedlist_deque.cpp b/chapter_stack_and_queue/linkedlist_deque.cpp new file mode 100644 index 0000000..1fb67ee --- /dev/null +++ b/chapter_stack_and_queue/linkedlist_deque.cpp @@ -0,0 +1,194 @@ +/** + * File: linkedlist_deque.cpp + * Created Time: 2023-03-02 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ˫ڵ */ +struct DoublyListNode { + int val; // ڵֵ + DoublyListNode *next; // ̽ڵָ + DoublyListNode *prev; // ǰڵָ + DoublyListNode(int val) : val(val), prev(nullptr), next(nullptr) { + } +}; + +/* ˫ʵֵ˫ */ +class LinkedListDeque { + private: + DoublyListNode *front, *rear; // ͷڵ front βڵ rear + int queSize = 0; // ˫еij + + public: + /* 췽 */ + LinkedListDeque() : front(nullptr), rear(nullptr) { + } + + /* */ + ~LinkedListDeque() { + // ɾڵ㣬ͷڴ + DoublyListNode *pre, *cur = front; + while (cur != nullptr) { + pre = cur; + cur = cur->next; + delete pre; + } + } + + /* ȡ˫еij */ + int size() { + return queSize; + } + + /* ж˫ǷΪ */ + bool isEmpty() { + return size() == 0; + } + + /* Ӳ */ + void push(int num, bool isFront) { + DoublyListNode *node = new DoublyListNode(num); + // Ϊգ front rear ָ node + if (isEmpty()) + front = rear = node; + // Ӳ + else if (isFront) { + // node ͷ + front->prev = node; + node->next = front; + front = node; // ͷڵ + // βӲ + } else { + // node β + rear->next = node; + node->prev = rear; + rear = node; // βڵ + } + queSize++; // ¶г + } + + /* */ + void pushFirst(int num) { + push(num, true); + } + + /* β */ + void pushLast(int num) { + push(num, false); + } + + /* Ӳ */ + int pop(bool isFront) { + if (isEmpty()) + throw out_of_range("Ϊ"); + int val; + // ׳Ӳ + if (isFront) { + val = front->val; // ݴͷڵֵ + // ɾͷڵ + DoublyListNode *fNext = front->next; + if (fNext != nullptr) { + fNext->prev = nullptr; + front->next = nullptr; + } + delete front; + front = fNext; // ͷڵ + // βӲ + } else { + val = rear->val; // ݴβڵֵ + // ɾβڵ + DoublyListNode *rPrev = rear->prev; + if (rPrev != nullptr) { + rPrev->next = nullptr; + rear->prev = nullptr; + } + delete rear; + rear = rPrev; // βڵ + } + queSize--; // ¶г + return val; + } + + /* ׳ */ + int popFirst() { + return pop(true); + } + + /* β */ + int popLast() { + return pop(false); + } + + /* ʶԪ */ + int peekFirst() { + if (isEmpty()) + throw out_of_range("˫Ϊ"); + return front->val; + } + + /* ʶβԪ */ + int peekLast() { + if (isEmpty()) + throw out_of_range("˫Ϊ"); + return rear->val; + } + + /* ڴӡ */ + vector toVector() { + DoublyListNode *node = front; + vector res(size()); + for (int i = 0; i < res.size(); i++) { + res[i] = node->val; + node = node->next; + } + return res; + } +}; + +/* Driver Code */ +int main() { + /* ʼ˫ */ + LinkedListDeque *deque = new LinkedListDeque(); + deque->pushLast(3); + deque->pushLast(2); + deque->pushLast(5); + cout << "˫ deque = "; + printVector(deque->toVector()); + + /* Ԫ */ + int peekFirst = deque->peekFirst(); + cout << "Ԫ peekFirst = " << peekFirst << endl; + int peekLast = deque->peekLast(); + cout << "βԪ peekLast = " << peekLast << endl; + + /* Ԫ */ + deque->pushLast(4); + cout << "Ԫ 4 βӺ deque ="; + printVector(deque->toVector()); + deque->pushFirst(1); + cout << "Ԫ 1 Ӻ deque = "; + printVector(deque->toVector()); + + /* Ԫس */ + int popLast = deque->popLast(); + cout << "βԪ = " << popLast << "βӺ deque = "; + printVector(deque->toVector()); + int popFirst = deque->popFirst(); + cout << "׳Ԫ = " << popFirst << "׳Ӻ deque = "; + printVector(deque->toVector()); + + /* ȡ˫еij */ + int size = deque->size(); + cout << "˫г size = " << size << endl; + + /* ж˫ǷΪ */ + bool isEmpty = deque->isEmpty(); + cout << "˫ǷΪ = " << boolalpha << isEmpty << endl; + + // ͷڴ + delete deque; + + return 0; +} diff --git a/chapter_stack_and_queue/linkedlist_queue.cpp b/chapter_stack_and_queue/linkedlist_queue.cpp new file mode 100644 index 0000000..9a7985e --- /dev/null +++ b/chapter_stack_and_queue/linkedlist_queue.cpp @@ -0,0 +1,120 @@ +/** + * File: linkedlist_queue.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ʵֵĶ */ +class LinkedListQueue { + private: + ListNode *front, *rear; // ͷڵ front βڵ rear + int queSize; + + public: + LinkedListQueue() { + front = nullptr; + rear = nullptr; + queSize = 0; + } + + ~LinkedListQueue() { + // ɾڵ㣬ͷڴ + freeMemoryLinkedList(front); + } + + /* ȡеij */ + int size() { + return queSize; + } + + /* ж϶ǷΪ */ + bool isEmpty() { + return queSize == 0; + } + + /* */ + void push(int num) { + // βڵ num + ListNode *node = new ListNode(num); + // Ϊգͷβڵ㶼ָýڵ + if (front == nullptr) { + front = node; + rear = node; + } + // вΪգ򽫸ýڵӵβڵ + else { + rear->next = node; + rear = node; + } + queSize++; + } + + /* */ + int pop() { + int num = peek(); + // ɾͷڵ + ListNode *tmp = front; + front = front->next; + // ͷڴ + delete tmp; + queSize--; + return num; + } + + /* ʶԪ */ + int peek() { + if (size() == 0) + throw out_of_range("Ϊ"); + return front->val; + } + + /* תΪ Vector */ + vector toVector() { + ListNode *node = front; + vector res(size()); + for (int i = 0; i < res.size(); i++) { + res[i] = node->val; + node = node->next; + } + return res; + } +}; + +/* Driver Code */ +int main() { + /* ʼ */ + LinkedListQueue *queue = new LinkedListQueue(); + + /* Ԫ */ + queue->push(1); + queue->push(3); + queue->push(2); + queue->push(5); + queue->push(4); + cout << " queue = "; + printVector(queue->toVector()); + + /* ʶԪ */ + int peek = queue->peek(); + cout << "Ԫ peek = " << peek << endl; + + /* Ԫس */ + peek = queue->pop(); + cout << "Ԫ pop = " << peek << "Ӻ queue = "; + printVector(queue->toVector()); + + /* ȡеij */ + int size = queue->size(); + cout << "г size = " << size << endl; + + /* ж϶ǷΪ */ + bool empty = queue->isEmpty(); + cout << "ǷΪ = " << empty << endl; + + // ͷڴ + delete queue; + + return 0; +} diff --git a/chapter_stack_and_queue/linkedlist_stack.cpp b/chapter_stack_and_queue/linkedlist_stack.cpp new file mode 100644 index 0000000..043f227 --- /dev/null +++ b/chapter_stack_and_queue/linkedlist_stack.cpp @@ -0,0 +1,109 @@ +/** + * File: linkedlist_stack.cpp + * Created Time: 2022-11-28 + * Author: qualifier1024 (2539244001@qq.com) + */ + +#include "../utils/common.hpp" + +/* ʵֵջ */ +class LinkedListStack { + private: + ListNode *stackTop; // ͷڵΪջ + int stkSize; // ջij + + public: + LinkedListStack() { + stackTop = nullptr; + stkSize = 0; + } + + ~LinkedListStack() { + // ɾڵ㣬ͷڴ + freeMemoryLinkedList(stackTop); + } + + /* ȡջij */ + int size() { + return stkSize; + } + + /* жջǷΪ */ + bool isEmpty() { + return size() == 0; + } + + /* ջ */ + void push(int num) { + ListNode *node = new ListNode(num); + node->next = stackTop; + stackTop = node; + stkSize++; + } + + /* ջ */ + int pop() { + int num = top(); + ListNode *tmp = stackTop; + stackTop = stackTop->next; + // ͷڴ + delete tmp; + stkSize--; + return num; + } + + /* ջԪ */ + int top() { + if (isEmpty()) + throw out_of_range("ջΪ"); + return stackTop->val; + } + + /* List תΪ Array */ + vector toVector() { + ListNode *node = stackTop; + vector res(size()); + for (int i = res.size() - 1; i >= 0; i--) { + res[i] = node->val; + node = node->next; + } + return res; + } +}; + +/* Driver Code */ +int main() { + /* ʼջ */ + LinkedListStack *stack = new LinkedListStack(); + + /* Ԫջ */ + stack->push(1); + stack->push(3); + stack->push(2); + stack->push(5); + stack->push(4); + cout << "ջ stack = "; + printVector(stack->toVector()); + + /* ջԪ */ + int top = stack->top(); + cout << "ջԪ top = " << top << endl; + + /* Ԫسջ */ + top = stack->pop(); + cout << "ջԪ pop = " << top << "ջ stack = "; + printVector(stack->toVector()); + + /* ȡջij */ + int size = stack->size(); + cout << "ջij size = " << size << endl; + + /* жǷΪ */ + bool empty = stack->isEmpty(); + cout << "ջǷΪ = " << empty << endl; + + // ͷڴ + delete stack; + + return 0; +} diff --git a/chapter_stack_and_queue/queue.cpp b/chapter_stack_and_queue/queue.cpp new file mode 100644 index 0000000..c8a5bb3 --- /dev/null +++ b/chapter_stack_and_queue/queue.cpp @@ -0,0 +1,41 @@ +/** + * File: queue.cpp + * Created Time: 2022-11-28 + * Author: qualifier1024 (2539244001@qq.com) + */ + +#include "../utils/common.hpp" + +/* Driver Code */ +int main() { + /* ʼ */ + queue queue; + + /* Ԫ */ + queue.push(1); + queue.push(3); + queue.push(2); + queue.push(5); + queue.push(4); + cout << " queue = "; + printQueue(queue); + + /* ʶԪ */ + int front = queue.front(); + cout << "Ԫ front = " << front << endl; + + /* Ԫس */ + queue.pop(); + cout << "Ԫ front = " << front << "Ӻ queue = "; + printQueue(queue); + + /* ȡеij */ + int size = queue.size(); + cout << "г size = " << size << endl; + + /* ж϶ǷΪ */ + bool empty = queue.empty(); + cout << "ǷΪ = " << empty << endl; + + return 0; +} diff --git a/chapter_stack_and_queue/stack.cpp b/chapter_stack_and_queue/stack.cpp new file mode 100644 index 0000000..55ec887 --- /dev/null +++ b/chapter_stack_and_queue/stack.cpp @@ -0,0 +1,41 @@ +/** + * File: stack.cpp + * Created Time: 2022-11-28 + * Author: qualifier1024 (2539244001@qq.com) + */ + +#include "../utils/common.hpp" + +/* Driver Code */ +int main() { + /* ʼջ */ + stack stack; + + /* Ԫջ */ + stack.push(1); + stack.push(3); + stack.push(2); + stack.push(5); + stack.push(4); + cout << "ջ stack = "; + printStack(stack); + + /* ջԪ */ + int top = stack.top(); + cout << "ջԪ top = " << top << endl; + + /* Ԫسջ */ + stack.pop(); // ޷ֵ + cout << "ջԪ pop = " << top << "ջ stack = "; + printStack(stack); + + /* ȡջij */ + int size = stack.size(); + cout << "ջij size = " << size << endl; + + /* жǷΪ */ + bool empty = stack.empty(); + cout << "ջǷΪ = " << empty << endl; + + return 0; +} diff --git a/chapter_tree/CMakeLists.txt b/chapter_tree/CMakeLists.txt new file mode 100644 index 0000000..fa7009b --- /dev/null +++ b/chapter_tree/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(avl_tree avl_tree.cpp) +add_executable(binary_search_tree binary_search_tree.cpp) +add_executable(binary_tree binary_tree.cpp) +add_executable(binary_tree_bfs binary_tree_bfs.cpp) +add_executable(binary_tree_dfs binary_tree_dfs.cpp) +add_executable(array_binary_tree array_binary_tree.cpp) \ No newline at end of file diff --git a/chapter_tree/array_binary_tree.cpp b/chapter_tree/array_binary_tree.cpp new file mode 100644 index 0000000..bf26c9d --- /dev/null +++ b/chapter_tree/array_binary_tree.cpp @@ -0,0 +1,137 @@ +/** + * File: array_binary_tree.cpp + * Created Time: 2023-07-19 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* ʾµĶ */ +class ArrayBinaryTree { + public: + /* 췽 */ + ArrayBinaryTree(vector arr) { + tree = arr; + } + + /* б */ + int size() { + return tree.size(); + } + + /* ȡΪ i ڵֵ */ + int val(int i) { + // Խ磬򷵻 INT_MAX λ + if (i < 0 || i >= size()) + return INT_MAX; + return tree[i]; + } + + /* ȡΪ i ڵӽڵ */ + int left(int i) { + return 2 * i + 1; + } + + /* ȡΪ i ڵӽڵ */ + int right(int i) { + return 2 * i + 2; + } + + /* ȡΪ i ڵĸڵ */ + int parent(int i) { + return (i - 1) / 2; + } + + /* */ + vector levelOrder() { + vector res; + // ֱӱ + for (int i = 0; i < size(); i++) { + if (val(i) != INT_MAX) + res.push_back(val(i)); + } + return res; + } + + /* ǰ */ + vector preOrder() { + vector res; + dfs(0, "pre", res); + return res; + } + + /* */ + vector inOrder() { + vector res; + dfs(0, "in", res); + return res; + } + + /* */ + vector postOrder() { + vector res; + dfs(0, "post", res); + return res; + } + + private: + vector tree; + + /* ȱ */ + void dfs(int i, string order, vector &res) { + // Ϊλ򷵻 + if (val(i) == INT_MAX) + return; + // ǰ + if (order == "pre") + res.push_back(val(i)); + dfs(left(i), order, res); + // + if (order == "in") + res.push_back(val(i)); + dfs(right(i), order, res); + // + if (order == "post") + res.push_back(val(i)); + } +}; + +/* Driver Code */ +int main() { + // ʼ + // ʹ INT_MAX λ nullptr + vector arr = {1, 2, 3, 4, INT_MAX, 6, 7, 8, 9, INT_MAX, INT_MAX, 12, INT_MAX, INT_MAX, 15}; + TreeNode *root = vectorToTree(arr); + cout << "\nʼ\n"; + cout << "ʾ\n"; + printVector(arr); + cout << "ʾ\n"; + printTree(root); + + // ʾµĶ + ArrayBinaryTree abt(arr); + + // ʽڵ + int i = 1; + int l = abt.left(i), r = abt.right(i), p = abt.parent(i); + cout << "\nǰڵΪ " << i << "ֵΪ " << abt.val(i) << "\n"; + cout << "ӽڵΪ " << l << "ֵΪ " << (l != INT_MAX ? to_string(abt.val(l)) : "nullptr") << "\n"; + cout << "ӽڵΪ " << r << "ֵΪ " << (r != INT_MAX ? to_string(abt.val(r)) : "nullptr") << "\n"; + cout << "丸ڵΪ " << p << "ֵΪ " << (p != INT_MAX ? to_string(abt.val(p)) : "nullptr") << "\n"; + + // + vector res = abt.levelOrder(); + cout << "\nΪ "; + printVector(res); + res = abt.preOrder(); + cout << "ǰΪ "; + printVector(res); + res = abt.inOrder(); + cout << "Ϊ "; + printVector(res); + res = abt.postOrder(); + cout << "Ϊ "; + printVector(res); + + return 0; +} diff --git a/chapter_tree/avl_tree.cpp b/chapter_tree/avl_tree.cpp new file mode 100644 index 0000000..85e62d5 --- /dev/null +++ b/chapter_tree/avl_tree.cpp @@ -0,0 +1,233 @@ +/** + * File: avl_tree.cpp + * Created Time: 2023-02-03 + * Author: what-is-me (whatisme@outlook.jp) + */ + +#include "../utils/common.hpp" + +/* AVL */ +class AVLTree { + public: + TreeNode *root; // ڵ + private: + /* ½ڵ߶ */ + void updateHeight(TreeNode *node) { + // ڵ߶ȵ߶ + 1 + node->height = max(height(node->left), height(node->right)) + 1; + } + + /* */ + TreeNode *rightRotate(TreeNode *node) { + TreeNode *child = node->left; + TreeNode *grandChild = child->right; + // child Ϊԭ㣬 node ת + child->right = node; + node->left = grandChild; + // ½ڵ߶ + updateHeight(node); + updateHeight(child); + // תĸڵ + return child; + } + + /* */ + TreeNode *leftRotate(TreeNode *node) { + TreeNode *child = node->right; + TreeNode *grandChild = child->left; + // child Ϊԭ㣬 node ת + child->left = node; + node->right = grandChild; + // ½ڵ߶ + updateHeight(node); + updateHeight(child); + // תĸڵ + return child; + } + + /* ִתʹ»ָƽ */ + TreeNode *rotate(TreeNode *node) { + // ȡڵ node ƽ + int _balanceFactor = balanceFactor(node); + // ƫ + if (_balanceFactor > 1) { + if (balanceFactor(node->left) >= 0) { + // + return rightRotate(node); + } else { + // + node->left = leftRotate(node->left); + return rightRotate(node); + } + } + // ƫ + if (_balanceFactor < -1) { + if (balanceFactor(node->right) <= 0) { + // + return leftRotate(node); + } else { + // + node->right = rightRotate(node->right); + return leftRotate(node); + } + } + // ƽתֱӷ + return node; + } + + /* ݹڵ㣨 */ + TreeNode *insertHelper(TreeNode *node, int val) { + if (node == nullptr) + return new TreeNode(val); + /* 1. Ҳλòڵ */ + if (val < node->val) + node->left = insertHelper(node->left, val); + else if (val > node->val) + node->right = insertHelper(node->right, val); + else + return node; // ظڵ㲻룬ֱӷ + updateHeight(node); // ½ڵ߶ + /* 2. ִתʹ»ָƽ */ + node = rotate(node); + // ĸڵ + return node; + } + + /* ݹɾڵ㣨 */ + TreeNode *removeHelper(TreeNode *node, int val) { + if (node == nullptr) + return nullptr; + /* 1. ҽڵ㲢ɾ */ + if (val < node->val) + node->left = removeHelper(node->left, val); + else if (val > node->val) + node->right = removeHelper(node->right, val); + else { + if (node->left == nullptr || node->right == nullptr) { + TreeNode *child = node->left != nullptr ? node->left : node->right; + // ӽڵ = 0 ֱɾ node + if (child == nullptr) { + delete node; + return nullptr; + } + // ӽڵ = 1 ֱɾ node + else { + delete node; + node = child; + } + } else { + // ӽڵ = 2 ¸ڵɾøýڵ滻ǰڵ + TreeNode *temp = node->right; + while (temp->left != nullptr) { + temp = temp->left; + } + int tempVal = temp->val; + node->right = removeHelper(node->right, temp->val); + node->val = tempVal; + } + } + updateHeight(node); // ½ڵ߶ + /* 2. ִתʹ»ָƽ */ + node = rotate(node); + // ĸڵ + return node; + } + + public: + /* ȡڵ߶ */ + int height(TreeNode *node) { + // սڵ߶Ϊ -1 Ҷڵ߶Ϊ 0 + return node == nullptr ? -1 : node->height; + } + + /* ȡƽ */ + int balanceFactor(TreeNode *node) { + // սڵƽΪ 0 + if (node == nullptr) + return 0; + // ڵƽ = ߶ - ߶ + return height(node->left) - height(node->right); + } + + /* ڵ */ + void insert(int val) { + root = insertHelper(root, val); + } + + /* ɾڵ */ + void remove(int val) { + root = removeHelper(root, val); + } + + /* ҽڵ */ + TreeNode *search(int val) { + TreeNode *cur = root; + // ѭңԽҶڵ + while (cur != nullptr) { + // Ŀڵ cur + if (cur->val < val) + cur = cur->right; + // Ŀڵ cur + else if (cur->val > val) + cur = cur->left; + // ҵĿڵ㣬ѭ + else + break; + } + // Ŀڵ + return cur; + } + + /*췽*/ + AVLTree() : root(nullptr) { + } + + /**/ + ~AVLTree() { + freeMemoryTree(root); + } +}; + +void testInsert(AVLTree &tree, int val) { + tree.insert(val); + cout << "\nڵ " << val << " AVL Ϊ" << endl; + printTree(tree.root); +} + +void testRemove(AVLTree &tree, int val) { + tree.remove(val); + cout << "\nɾڵ " << val << " AVL Ϊ" << endl; + printTree(tree.root); +} + +/* Driver Code */ +int main() { + /* ʼ AVL */ + AVLTree avlTree; + + /* ڵ */ + // עڵAVL αƽ + testInsert(avlTree, 1); + testInsert(avlTree, 2); + testInsert(avlTree, 3); + testInsert(avlTree, 4); + testInsert(avlTree, 5); + testInsert(avlTree, 8); + testInsert(avlTree, 7); + testInsert(avlTree, 9); + testInsert(avlTree, 10); + testInsert(avlTree, 6); + + /* ظڵ */ + testInsert(avlTree, 7); + + /* ɾڵ */ + // עɾڵAVL αƽ + testRemove(avlTree, 8); // ɾΪ 0 Ľڵ + testRemove(avlTree, 5); // ɾΪ 1 Ľڵ + testRemove(avlTree, 4); // ɾΪ 2 Ľڵ + + /* ѯڵ */ + TreeNode *node = avlTree.search(7); + cout << "\nҵĽڵΪ " << node << "ڵֵ = " << node->val << endl; +} diff --git a/chapter_tree/binary_search_tree.cpp b/chapter_tree/binary_search_tree.cpp new file mode 100644 index 0000000..33347c4 --- /dev/null +++ b/chapter_tree/binary_search_tree.cpp @@ -0,0 +1,170 @@ +/** + * File: binary_search_tree.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +class BinarySearchTree { + private: + TreeNode *root; + + public: + /* 췽 */ + BinarySearchTree() { + // ʼ + root = nullptr; + } + + /* */ + ~BinarySearchTree() { + freeMemoryTree(root); + } + + /* ȡڵ */ + TreeNode *getRoot() { + return root; + } + + /* ҽڵ */ + TreeNode *search(int num) { + TreeNode *cur = root; + // ѭңԽҶڵ + while (cur != nullptr) { + // Ŀڵ cur + if (cur->val < num) + cur = cur->right; + // Ŀڵ cur + else if (cur->val > num) + cur = cur->left; + // ҵĿڵ㣬ѭ + else + break; + } + // Ŀڵ + return cur; + } + + /* ڵ */ + void insert(int num) { + // Ϊգʼڵ + if (root == nullptr) { + root = new TreeNode(num); + return; + } + TreeNode *cur = root, *pre = nullptr; + // ѭңԽҶڵ + while (cur != nullptr) { + // ҵظڵ㣬ֱӷ + if (cur->val == num) + return; + pre = cur; + // λ cur + if (cur->val < num) + cur = cur->right; + // λ cur + else + cur = cur->left; + } + // ڵ + TreeNode *node = new TreeNode(num); + if (pre->val < num) + pre->right = node; + else + pre->left = node; + } + + /* ɾڵ */ + void remove(int num) { + // Ϊգֱǰ + if (root == nullptr) + return; + TreeNode *cur = root, *pre = nullptr; + // ѭңԽҶڵ + while (cur != nullptr) { + // ҵɾڵ㣬ѭ + if (cur->val == num) + break; + pre = cur; + // ɾڵ cur + if (cur->val < num) + cur = cur->right; + // ɾڵ cur + else + cur = cur->left; + } + // ޴ɾڵ㣬ֱӷ + if (cur == nullptr) + return; + // ӽڵ = 0 or 1 + if (cur->left == nullptr || cur->right == nullptr) { + // ӽڵ = 0 / 1 ʱ child = nullptr / ӽڵ + TreeNode *child = cur->left != nullptr ? cur->left : cur->right; + // ɾڵ cur + if (cur != root) { + if (pre->left == cur) + pre->left = child; + else + pre->right = child; + } else { + // ɾڵΪڵ㣬ָڵ + root = child; + } + // ͷڴ + delete cur; + } + // ӽڵ = 2 + else { + // ȡ cur һڵ + TreeNode *tmp = cur->right; + while (tmp->left != nullptr) { + tmp = tmp->left; + } + int tmpVal = tmp->val; + // ݹɾڵ tmp + remove(tmp->val); + // tmp cur + cur->val = tmpVal; + } + } +}; + +/* Driver Code */ +int main() { + /* ʼ */ + BinarySearchTree *bst = new BinarySearchTree(); + // ע⣬ͬIJ˳ɲͬĶпһ + vector nums = {8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15}; + for (int num : nums) { + bst->insert(num); + } + cout << endl << "ʼĶΪ\n" << endl; + printTree(bst->getRoot()); + + /* ҽڵ */ + TreeNode *node = bst->search(7); + cout << endl << "ҵĽڵΪ " << node << "ڵֵ = " << node->val << endl; + + /* ڵ */ + bst->insert(16); + cout << endl << "ڵ 16 󣬶Ϊ\n" << endl; + printTree(bst->getRoot()); + + /* ɾڵ */ + bst->remove(1); + cout << endl << "ɾڵ 1 󣬶Ϊ\n" << endl; + printTree(bst->getRoot()); + bst->remove(2); + cout << endl << "ɾڵ 2 󣬶Ϊ\n" << endl; + printTree(bst->getRoot()); + bst->remove(4); + cout << endl << "ɾڵ 4 󣬶Ϊ\n" << endl; + printTree(bst->getRoot()); + + // ͷڴ + delete bst; + + return 0; +} diff --git a/chapter_tree/binary_tree.cpp b/chapter_tree/binary_tree.cpp new file mode 100644 index 0000000..9104e4d --- /dev/null +++ b/chapter_tree/binary_tree.cpp @@ -0,0 +1,43 @@ +/** + * File: binary_tree.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* Driver Code */ +int main() { + /* ʼ */ + // ʼڵ + TreeNode *n1 = new TreeNode(1); + TreeNode *n2 = new TreeNode(2); + TreeNode *n3 = new TreeNode(3); + TreeNode *n4 = new TreeNode(4); + TreeNode *n5 = new TreeNode(5); + // ڵ֮ãָ룩 + n1->left = n2; + n1->right = n3; + n2->left = n4; + n2->right = n5; + cout << endl << "ʼ\n" << endl; + printTree(n1); + + /* ɾڵ */ + TreeNode *P = new TreeNode(0); + // n1 -> n2 мڵ P + n1->left = P; + P->left = n2; + cout << endl << "ڵ P \n" << endl; + printTree(n1); + // ɾڵ P + n1->left = n2; + delete P; // ͷڴ + cout << endl << "ɾڵ P \n" << endl; + printTree(n1); + + // ͷڴ + freeMemoryTree(n1); + + return 0; +} diff --git a/chapter_tree/binary_tree_bfs.cpp b/chapter_tree/binary_tree_bfs.cpp new file mode 100644 index 0000000..8cb1b45 --- /dev/null +++ b/chapter_tree/binary_tree_bfs.cpp @@ -0,0 +1,42 @@ +/** + * File: binary_tree_bfs.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* */ +vector levelOrder(TreeNode *root) { + // ʼУڵ + queue queue; + queue.push(root); + // ʼһбڱ + vector vec; + while (!queue.empty()) { + TreeNode *node = queue.front(); + queue.pop(); // г + vec.push_back(node->val); // ڵֵ + if (node->left != nullptr) + queue.push(node->left); // ӽڵ + if (node->right != nullptr) + queue.push(node->right); // ӽڵ + } + return vec; +} + +/* Driver Code */ +int main() { + /* ʼ */ + // һֱɶĺ + TreeNode *root = vectorToTree(vector{1, 2, 3, 4, 5, 6, 7}); + cout << endl << "ʼ\n" << endl; + printTree(root); + + /* */ + vector vec = levelOrder(root); + cout << endl << "Ľڵӡ = "; + printVector(vec); + + return 0; +} diff --git a/chapter_tree/binary_tree_dfs.cpp b/chapter_tree/binary_tree_dfs.cpp new file mode 100644 index 0000000..534c668 --- /dev/null +++ b/chapter_tree/binary_tree_dfs.cpp @@ -0,0 +1,69 @@ +/** + * File: binary_tree_dfs.cpp + * Created Time: 2022-11-25 + * Author: krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +// ʼбڴ洢 +vector vec; + +/* ǰ */ +void preOrder(TreeNode *root) { + if (root == nullptr) + return; + // ȼڵ -> -> + vec.push_back(root->val); + preOrder(root->left); + preOrder(root->right); +} + +/* */ +void inOrder(TreeNode *root) { + if (root == nullptr) + return; + // ȼ -> ڵ -> + inOrder(root->left); + vec.push_back(root->val); + inOrder(root->right); +} + +/* */ +void postOrder(TreeNode *root) { + if (root == nullptr) + return; + // ȼ -> -> ڵ + postOrder(root->left); + postOrder(root->right); + vec.push_back(root->val); +} + +/* Driver Code */ +int main() { + /* ʼ */ + // һֱɶĺ + TreeNode *root = vectorToTree(vector{1, 2, 3, 4, 5, 6, 7}); + cout << endl << "ʼ\n" << endl; + printTree(root); + + /* ǰ */ + vec.clear(); + preOrder(root); + cout << endl << "ǰĽڵӡ = "; + printVector(vec); + + /* */ + vec.clear(); + inOrder(root); + cout << endl << "Ľڵӡ = "; + printVector(vec); + + /* */ + vec.clear(); + postOrder(root); + cout << endl << "Ľڵӡ = "; + printVector(vec); + + return 0; +} diff --git a/test/priority_queue_demo.cpp b/test/priority_queue_demo.cpp new file mode 100644 index 0000000..cf7ebe6 --- /dev/null +++ b/test/priority_queue_demo.cpp @@ -0,0 +1,28 @@ +#include +#include + +struct Person { + std::string name; + int age; +}; + +struct CompareByAge { + bool operator()(const Person& p1, const Person& p2) const { + return p1.age < p2.age; + } +}; + +int main() { + std::priority_queue, CompareByAge> pq; + + pq.push({"Alice", 25}); + pq.push({"Bob", 30}); + pq.push({"Charlie", 20}); + + while (!pq.empty()) { + std::cout << pq.top().name << " "; + pq.pop(); + } + + return 0; +} \ No newline at end of file diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt new file mode 100644 index 0000000..775a558 --- /dev/null +++ b/utils/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(utils + common.hpp print_utils.hpp + list_node.hpp tree_node.hpp + vertex.hpp) \ No newline at end of file diff --git a/utils/common.hpp b/utils/common.hpp new file mode 100644 index 0000000..c72dabd --- /dev/null +++ b/utils/common.hpp @@ -0,0 +1,28 @@ +/** + * File: common.hpp + * Created Time: 2021-12-19 + * Author: krahets (krahets@163.com) + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "list_node.hpp" +#include "print_utils.hpp" +#include "tree_node.hpp" +#include "vertex.hpp" + +using namespace std; diff --git a/utils/list_node.hpp b/utils/list_node.hpp new file mode 100644 index 0000000..b68d49c --- /dev/null +++ b/utils/list_node.hpp @@ -0,0 +1,59 @@ +/** + * File: list_node.hpp + * Created Time: 2021-12-19 + * Author: krahets (krahets@163.com) + */ + +#pragma once + +#include +#include + +using namespace std; + +/* Definition for a singly-linked list node */ +struct ListNode +{ + int val; // ǽڵֵ + ListNode *next; // ָһڵָ + ListNode(int x) : val(x), next(nullptr) + { // 캯: ʼڵֵΪx, ָһڵָΪ + } +}; + +/* Generate a linked list with a vector */ // һvectorһ +ListNode *vecToLinkedList(vector list) +{ + ListNode *dum = new ListNode(0); // һڵ dum (ֵΪ0) + ListNode *head = dum; // һָڵָ head + for (int val : list) + { + head->next = new ListNode(val); // һ½ڵ, ֵΪval, ָ븳head->next + head = head->next; // headָһڵ + } + return dum->next; // ͷڵ +} + +/* Get a list node with specific value from a linked list */ +ListNode *getListNode(ListNode *head, int val) +{ + // , ҵֵΪvalĽڵ + while (head != nullptr && head->val != val) + { + head = head->next; // ָһڵ + } + return head; // ҵĽڵ, ûҵ, nullptr +} + +/* Free the memory allocated to a linked list */ +void freeMemoryLinkedList(ListNode *cur) +{ + // ͷڴ + ListNode *pre; + while (cur != nullptr) // ǰڵ㲻Ϊ + { + pre = cur; // preָǰڵ + cur = cur->next; // ǰڵָһڵ + delete pre; // ͷpreָĽڵ + } +} diff --git a/utils/print_utils.hpp b/utils/print_utils.hpp new file mode 100644 index 0000000..6686644 --- /dev/null +++ b/utils/print_utils.hpp @@ -0,0 +1,289 @@ +/** + * File: print_utils.hpp + * Created Time: 2021-12-19 + * Author: krahets (krahets@163.com), msk397 (machangxinq@gmail.com), LoneRanger(836253168@qq.com) + */ + +#pragma once + +#include "list_node.hpp" +#include "tree_node.hpp" +#include +#include +#include +#include + +/* Find an element in a vector */ // һ vector вԪ +template +int vecFind(const vector &vec, T ele) +{ + int j = INT_MAX; + for (int i = 0; i < vec.size(); i++) + { + if (vec[i] == ele) // ҵԪʱԪص± + { + j = i; + } + } + return j; +} + +/* Concatenate a vector with a delim */ // һ vector ָķָӳַ +template +string strJoin(const string &delim, const T &vec) // delim Ƿָvec vector(ʹ&vecʾݵ, ǿ, Ч) +{ + ostringstream s; // һ + for (const auto &i : vec) + { + if (&i != &vec[0]) + { + s << delim; // ָӵ + } + s << i; // Ԫӵ + } + return s.str(); // .str() ijԱڷַʾ +} + +/* Repeat a string for n times */ // һַظ n +string strRepeat(string str, int n) +{ + ostringstream os; // һ + for (int i = 0; i < n; i++) + os << str; // ַظ n + return os.str(); // ַʾ +} + +/* Print an Array */ // ӡһ +template +void printArray(T *arr, int n) // arr ׵ַn ij +{ + cout << "["; + for (int i = 0; i < n - 1; i++) + { + cout << arr[i] << ", "; // ӡԪ + } + if (n >= 1) // 鳤ȴڵ 1 ʱ + cout << arr[n - 1] << "]" << endl; // ӡһԪ һ ']' + else + cout << "]" << endl; // 鳤Ϊ 0 ʱֱӴӡһ ']' +} + +/* Get the Vector String object */ // ȡһ vector ַʾ +template +string getVectorString(vector &list) // list vector +{ + return "[" + strJoin(", ", list) + "]"; // ʹ strJoin vector öӳַַ '[' ']' +} + +/* Print a vector */ // ӡһ vector +template +void printVector(vector list) +{ + cout << getVectorString(list) << '\n'; // ʹ getVectorString ȡ vector ַʾӡ +} + +/* Print a vector matrix */ // ӡһ vector +template +void printVectorMatrix(vector> &matrix) // matrix һά vector, ÿԪضһ vector, ڱʾ () +{ + cout << "[" << '\n'; + for (vector &list : matrix) // matrix еÿһ vector Ԫ + cout << " " + getVectorString(list) + "," << '\n'; // ʹ getVectorString ȡ vector ַʾӡ + cout << "]" << '\n'; +} + +/* Print a linked list */ // ӡһ +void printLinkedList(ListNode *head) +{ + vector list; // һ vector ڴ洢Ԫ + while (head != nullptr) // : ָ벻Ϊʱ, + { + list.push_back(head->val); // Ԫӵ vector + head = head->next; // ָָһԪ + } + + cout << strJoin(" -> ", list) << '\n'; // ʹ strJoin vector üͷӳַӡ +} + +/** + * This tree printer is borrowed from TECHIE DELIGHT // ӡǴ TECHIE DELIGHT õ + * https://www.techiedelight.com/c-program-print-binary-tree/ + */ +struct Trunk // ɽṹ +{ + Trunk *prev; // ָһ + string str; // ɵַʾ + Trunk(Trunk *prev, string str) // 캯 cpp е struct Ҳй캯 + { + this->prev = prev; + this->str = str; + } +}; + +/* Helper function to print branches of the binary tree */ // ڴӡĸ +void showTrunks(Trunk *p) +{ + if (p == nullptr) // Ϊʱֱӷ + { + return; + } + + // ݹõ˳ӡ˳෴ + showTrunks(p->prev); // ݹ showTrunks + cout << p->str; // ӡɵַʾ +} + +/* Print a binary tree */ // ӡһ +void printTree(TreeNode *root, Trunk *prev, bool isRight) +{ + if (root == nullptr) + { + return; + } + + string prev_str = " "; // ʼ prev_str Ϊո + Trunk trunk(prev, prev_str); // һɶ + + printTree(root->right, &trunk, true); // ݹ printTree ӡ + + if (!prev) // Ϊʱ + { + trunk.str = ""; // ɵַʾΪ "" + } + else if (isRight) // ɲΪʱ + { + trunk.str = "/"; // ɵַʾΪ "/" + prev_str = " |"; // prev_str Ϊ " |" + } + else // ɲΪҲʱ + { + trunk.str = "\\"; // ɵַʾΪ "\" + prev->str = prev_str; // prev_str Ϊ prev->str + } + + showTrunks(&trunk); // showTrunks ӡ + cout << " " << root->val << endl; // ӡڵֵ + + if (prev) // ɲΪʱ + { + prev->str = prev_str; // prev->str Ϊ prev_str + } + trunk.str = " |"; // ɵַʾΪ " |" + + printTree(root->left, &trunk, false); // ݹ printTree ӡ +} + +/* The interface of the tree printer */ // ӡĽӿ (: ĿΪ˷) +void printTree(TreeNode *root) +{ + printTree(root, nullptr, false); // printTree (ذ汾) +} + +/* Print a stack */ // ӡһջ +template +void printStack(stack stk) +{ + // Reverse the input stack // תջ + stack tmp; // һʱջ + while (!stk.empty()) // ջΪʱ (ջ) + { + tmp.push(stk.top()); // ջԪӵʱջ + stk.pop(); // ջԪ + } + + // Generate the string to print // Ҫӡַ + ostringstream s; // һ + bool flag = true; // һ־λ (ĬΪ true), ǷǵһԪ + while (!tmp.empty()) + { + if (flag) + { + s << tmp.top(); // ־λΪ true ʱջԪӵ + flag = false; // ־λΪ false + } + else // ־λΪ false ʱ + s << ", " << tmp.top(); // ջԪӵ + tmp.pop(); // ջԪ + } + cout << "[" + s.str() + "]" << '\n'; // ʹַʾӡ +} + +/* Print a queue */ // ӡһ +template +void printQueue(queue queue) // queue Ƕ +{ + // Generate the string to print // Ҫӡַ + ostringstream s; + bool flag = true; + while (!queue.empty()) + { + if (flag) + { + s << queue.front(); // ־λΪ true ʱеĶԪӵ (true ʾǵһԪ) + flag = false; + } + else + s << ", " << queue.front(); // ־λΪ false ʱеĶԪǰһţӵ + queue.pop(); // Ԫ + } + cout << "[" + s.str() + "]" << '\n'; // ʹַʾӡ +} + +/* Print a deque */ // ӡһ˫˶ +template +void printDeque(deque deque) // deque ˫˶( deck) +{ + // Generate the string to print // Ҫӡַ + ostringstream s; + bool flag = true; + while (!deque.empty()) // ˫˶вΪʱ + { + if (flag) + { + s << deque.front(); + flag = false; + } + else + s << ", " << deque.front(); + deque.pop_front(); // Ԫ + } + cout << "[" + s.str() + "]" << '\n'; +} + +/* Print a HashMap */ // ӡһϣ +// ģ TKey TValue ֵָԵ +template +void printHashMap(unordered_map map) // map ǹϣ +{ + for (auto kv : map) // auto ؼԶƵ + { + cout << kv.first << " -> " << kv.second << '\n'; // .first ʾ.second ʾֵ + } +} + +/* Expose the underlying storage of the priority_queue container */ // ¶ȶĵײ洢 +template +S &Container(priority_queue &pq) // pq ȶ +{ + struct HackedQueue : private priority_queue // һ˽м̳еȶ + { + static S &Container(priority_queue &pq) // һ̬Ա Container + { + return pq.*&HackedQueue::c; // ȶеĵײ洢 + } + }; + return HackedQueue::Container(pq); // þ̬Ա Container +} + +/* Print a Heap (PriorityQueue) */ // ӡһѣȶУ +template +void printHeap(priority_queue &heap) // heap ȶ +{ + vector vec = Container(heap); // ȡȶеĵײ洢 + cout << "ѵʾ"; + printVector(vec); + cout << "ѵ״ʾ" << endl; + TreeNode *root = vectorToTree(vec); // ½һ rootȶеĵײ洢תΪ + printTree(root); + freeMemoryTree(root); +} diff --git a/utils/tree_node.hpp b/utils/tree_node.hpp new file mode 100644 index 0000000..de54044 --- /dev/null +++ b/utils/tree_node.hpp @@ -0,0 +1,120 @@ +/** + * File: tree_node.hpp + * Created Time: 2021-12-19 + * Author: krahets (krahets@163.com) + */ + +#pragma once + +#include +#include + +using namespace std; + +/* ڵṹ */ +struct TreeNode +{ + int val{}; // ڵֵ val {} ʾʼΪ 0 nullptr ({} C++11 : ֵʼ) + int height = 0; // ڵĸ߶ + TreeNode *parent{}; // ڵ {} ʾʼΪ nullptr + TreeNode *left{}; // {} ʾʼΪ nullptr + TreeNode *right{}; // Һ {} ʾʼΪ nullptr + TreeNode() = default; // ĬϹ캯 + explicit TreeNode(int x, TreeNode *parent = nullptr) : val(x), parent(parent) + { + } // 캯: ʼڵֵΪx, ڵΪparent +}; + +// лο +// https://www.hello-algo.com/chapter_tree/array_representation_of_tree/ +// ʾ +// [1, 2, 3, 4, None, 6, 7, 8, 9, None, None, 12, None, None, 15] +// ʾ +// / 15 +// / 7 +// / 3 +// | \ 6 +// | \ 12 +// 1 +// \ 2 +// | / 9 +// \ 4 +// \ 8 + +/* блΪݹ */ +/* + vectorToTreeDFS һݹ麯ڽһ͵ arr תΪһöĸڵ㡣 + IJ arr iarr һ洢ֵi ǵǰڵе + ȼ鵱ǰ i ǷԽ߶ӦֵǷΪ INT_MAXǵĻʾǰڵΪսڵ㣬 nullptr + ǰڵ㲻Ϊգᴴһµ TreeNode 󣬲 arr[i] ֵڵ val Ա + Ȼ󣬺ݹ vectorToTreeDFS ǰڵΪ 2 * i + 1Ϊ 2 * i + 2ݹõĿǽ arr еԪתΪĽڵ㣬ڵ֮ĸӹϵ + 󣬺ظڵ㣬ת̡ + ʹDFSķʽͨݹδÿڵ㣬Ķṹ +*/ +TreeNode *vectorToTreeDFS(vector &arr, int i) +{ + if (i < 0 || i >= arr.size() || arr[i] == INT_MAX) + { + return nullptr; + } + TreeNode *root = new TreeNode(arr[i]); + root->left = vectorToTreeDFS(arr, 2 * i + 1); // ݹ鹹 + root->right = vectorToTreeDFS(arr, 2 * i + 2); // ݹ鹹 + return root; // ظڵ +} + +/* блΪ */ +TreeNode *vectorToTree(vector arr) +{ + return vectorToTreeDFS(arr, 0); +} + +/* лΪбݹ */ +/* +treeToVecorDFS һݹ麯ڽĽڵֵDFS˳洢һС + +IJ + +rootָǰڵָ룬ʾǰݹĽڵ㡣 +iʾǰڵеλá +res洢ڵֵá +ʵ߼£ + +ȣ鵱ǰڵǷΪաΪգʾѾҶӽڵսڵ㣬ֱӷء +Ȼͨһѭ res չ㹻ijȣԱܹ洢ǰڵֵѭ i ڵ res ĴС + res УΪ i λõֵΪǰڵֵ +ݹ treeToVecorDFS ֱǰڵӽڵӽڵ㡣ӽڵ㣬λΪ 2 * i + 1ӽڵ㣬λΪ 2 * i + 2 +ǽĽڵֵ˳洢һУںݴ +*/ +void treeToVecorDFS(TreeNode *root, int i, vector &res) +{ + if (root == nullptr) + return; + while (i >= res.size()) + { + res.push_back(INT_MAX); // ʼΪ INT_MAX + } + res[i] = root->val; + treeToVecorDFS(root->left, 2 * i + 1, res); + treeToVecorDFS(root->right, 2 * i + 2, res); +} + +/* лΪб */ +vector treeToVecor(TreeNode *root) +{ + vector res; + treeToVecorDFS(root, 0, res); + return res; +} + +/* ͷŶڴ */ +void freeMemoryTree(TreeNode *root) +{ + if (root == nullptr) + return; + + // Ҫεݹͷڴ棬ͷŸڵڴ + freeMemoryTree(root->left); + freeMemoryTree(root->right); + delete root; +} diff --git a/utils/vertex.hpp b/utils/vertex.hpp new file mode 100644 index 0000000..d40316d --- /dev/null +++ b/utils/vertex.hpp @@ -0,0 +1,42 @@ +/** + * File: vertex.hpp + * Created Time: 2023-03-02 + * Author: krahets (krahets@163.com) + */ + +#pragma once // ֹͷļظ + +#include + +using namespace std; + +/* */ +struct Vertex +{ + int val; + Vertex(int x) : val(x) + { + } +}; + +/* ֵб vals ضб vets */ +vector valsToVets(vector vals) +{ + vector vets; + for (int val : vals) + { + vets.push_back(new Vertex(val)); + } + return vets; +} + +/* 붥б vets ֵб vals */ +vector vetsToVals(vector vets) +{ + vector vals; + for (Vertex *vet : vets) + { + vals.push_back(vet->val); + } + return vals; +}