From 967293c421d1dc0e41d1e5d7a73138024667a36f Mon Sep 17 00:00:00 2001 From: krahets Date: Sun, 29 Mar 2026 05:06:58 +0800 Subject: [PATCH] build --- ru/docs/chapter_array_and_linkedlist/array.md | 229 +----- .../linked_list.md | 98 +-- ru/docs/chapter_array_and_linkedlist/list.md | 24 +- .../backtracking_algorithm.md | 174 +--- .../chapter_backtracking/n_queens_problem.md | 43 +- .../permutations_problem.md | 82 +- .../subset_sum_problem.md | 117 +-- .../iteration_and_recursion.md | 222 +----- .../space_complexity.md | 275 +------ .../time_complexity.md | 747 +----------------- .../binary_search_recur.md | 36 +- .../build_binary_tree_problem.md | 40 +- .../hanota_problem.md | 56 +- .../dp_problem_features.md | 24 +- .../dp_solution_pipeline.md | 120 +-- .../edit_distance_problem.md | 112 +-- .../intro_to_dynamic_programming.md | 114 +-- .../knapsack_problem.md | 121 +-- .../unbounded_knapsack_problem.md | 95 +-- ru/docs/chapter_graph/graph_operations.md | 48 +- ru/docs/chapter_graph/graph_traversal.md | 48 +- .../fractional_knapsack_problem.md | 27 +- ru/docs/chapter_greedy/greedy_algorithm.md | 8 +- .../chapter_greedy/max_capacity_problem.md | 8 +- .../max_product_cutting_problem.md | 8 +- ru/docs/chapter_hashing/hash_algorithm.md | 92 +-- ru/docs/chapter_hashing/hash_collision.md | 54 +- ru/docs/chapter_hashing/hash_map.md | 44 +- ru/docs/chapter_heap/build_heap.md | 14 +- ru/docs/chapter_heap/heap.md | 443 +---------- ru/docs/chapter_heap/top_k.md | 34 +- ru/docs/chapter_searching/binary_search.md | 38 +- .../chapter_searching/binary_search_edge.md | 31 +- .../binary_search_insertion.md | 37 +- .../replace_linear_by_hashing.md | 28 +- ru/docs/chapter_sorting/bubble_sort.md | 31 +- ru/docs/chapter_sorting/bucket_sort.md | 8 +- ru/docs/chapter_sorting/counting_sort.md | 36 +- ru/docs/chapter_sorting/heap_sort.md | 34 +- ru/docs/chapter_sorting/insertion_sort.md | 8 +- ru/docs/chapter_sorting/merge_sort.md | 51 +- ru/docs/chapter_sorting/quick_sort.md | 269 +------ ru/docs/chapter_sorting/radix_sort.md | 60 +- ru/docs/chapter_sorting/selection_sort.md | 8 +- ru/docs/chapter_stack_and_queue/deque.md | 80 +- ru/docs/chapter_stack_and_queue/queue.md | 48 +- ru/docs/chapter_stack_and_queue/stack.md | 44 +- .../array_representation_of_tree.md | 33 +- ru/docs/chapter_tree/avl_tree.md | 739 +---------------- ru/docs/chapter_tree/binary_search_tree.md | 147 +--- ru/docs/chapter_tree/binary_tree_traversal.md | 74 +- 51 files changed, 288 insertions(+), 5073 deletions(-) diff --git a/ru/docs/chapter_array_and_linkedlist/array.md b/ru/docs/chapter_array_and_linkedlist/array.md index 5151fc37d..43915894d 100644 --- a/ru/docs/chapter_array_and_linkedlist/array.md +++ b/ru/docs/chapter_array_and_linkedlist/array.md @@ -307,13 +307,7 @@ comments: true === "Ruby" ```ruby title="array.rb" - =begin - File: array.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Случайный доступ к элементу ### + ### Случайный доступ к элементу ### def random_access(nums) # Случайным образом выбрать число из интервала [0, nums.length) random_index = Random.rand(0...nums.length) @@ -507,39 +501,7 @@ comments: true === "Ruby" ```ruby title="array.rb" - =begin - File: array.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Случайный доступ к элементу ### - def random_access(nums) - # Случайным образом выбрать число из интервала [0, nums.length) - random_index = Random.rand(0...nums.length) - - # Получить и вернуть случайный элемент - nums[random_index] - end - - - # ## Увеличить длину массива ### - # Обратите внимание: Array в Ruby является динамическим массивом и может быть расширен напрямую - # Для удобства обучения эта функция рассматривает Array как массив неизменяемой длины - def extend(nums, enlarge) - # Инициализировать массив увеличенной длины - res = Array.new(nums.length + enlarge, 0) - - # Скопировать все элементы исходного массива в новый массив - for i in 0...nums.length - res[i] = nums[i] - end - - # Вернуть новый массив после расширения - res - end - - # ## Вставка элемента num по индексу index в массив ### + ### Вставка элемента num по индексу index в массив ### def insert(nums, num, index) # Сдвинуть элемент с индексом index и все последующие элементы на одну позицию назад for i in (nums.length - 1).downto(index + 1) @@ -712,51 +674,7 @@ comments: true === "Ruby" ```ruby title="array.rb" - =begin - File: array.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Случайный доступ к элементу ### - def random_access(nums) - # Случайным образом выбрать число из интервала [0, nums.length) - random_index = Random.rand(0...nums.length) - - # Получить и вернуть случайный элемент - nums[random_index] - end - - - # ## Увеличить длину массива ### - # Обратите внимание: Array в Ruby является динамическим массивом и может быть расширен напрямую - # Для удобства обучения эта функция рассматривает Array как массив неизменяемой длины - def extend(nums, enlarge) - # Инициализировать массив увеличенной длины - res = Array.new(nums.length + enlarge, 0) - - # Скопировать все элементы исходного массива в новый массив - for i in 0...nums.length - res[i] = nums[i] - end - - # Вернуть новый массив после расширения - res - end - - # ## Вставка элемента num по индексу index в массив ### - def insert(nums, num, index) - # Сдвинуть элемент с индексом index и все последующие элементы на одну позицию назад - for i in (nums.length - 1).downto(index + 1) - nums[i] = nums[i - 1] - end - - # Присвоить num элементу по индексу index - nums[index] = num - end - - - # ## Удаление элемента по индексу index ### + ### Удаление элемента по индексу index ### def remove(nums, index) # Сдвинуть все элементы после индекса index на одну позицию вперед for i in index...(nums.length - 1) @@ -996,59 +914,7 @@ comments: true === "Ruby" ```ruby title="array.rb" - =begin - File: array.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Случайный доступ к элементу ### - def random_access(nums) - # Случайным образом выбрать число из интервала [0, nums.length) - random_index = Random.rand(0...nums.length) - - # Получить и вернуть случайный элемент - nums[random_index] - end - - - # ## Увеличить длину массива ### - # Обратите внимание: Array в Ruby является динамическим массивом и может быть расширен напрямую - # Для удобства обучения эта функция рассматривает Array как массив неизменяемой длины - def extend(nums, enlarge) - # Инициализировать массив увеличенной длины - res = Array.new(nums.length + enlarge, 0) - - # Скопировать все элементы исходного массива в новый массив - for i in 0...nums.length - res[i] = nums[i] - end - - # Вернуть новый массив после расширения - res - end - - # ## Вставка элемента num по индексу index в массив ### - def insert(nums, num, index) - # Сдвинуть элемент с индексом index и все последующие элементы на одну позицию назад - for i in (nums.length - 1).downto(index + 1) - nums[i] = nums[i - 1] - end - - # Присвоить num элементу по индексу index - nums[index] = num - end - - - # ## Удаление элемента по индексу index ### - def remove(nums, index) - # Сдвинуть все элементы после индекса index на одну позицию вперед - for i in index...(nums.length - 1) - nums[i] = nums[i + 1] - end - end - - # ## Обход массива ### + ### Обход массива ### def traverse(nums) count = 0 @@ -1236,74 +1102,7 @@ comments: true === "Ruby" ```ruby title="array.rb" - =begin - File: array.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Случайный доступ к элементу ### - def random_access(nums) - # Случайным образом выбрать число из интервала [0, nums.length) - random_index = Random.rand(0...nums.length) - - # Получить и вернуть случайный элемент - nums[random_index] - end - - - # ## Увеличить длину массива ### - # Обратите внимание: Array в Ruby является динамическим массивом и может быть расширен напрямую - # Для удобства обучения эта функция рассматривает Array как массив неизменяемой длины - def extend(nums, enlarge) - # Инициализировать массив увеличенной длины - res = Array.new(nums.length + enlarge, 0) - - # Скопировать все элементы исходного массива в новый массив - for i in 0...nums.length - res[i] = nums[i] - end - - # Вернуть новый массив после расширения - res - end - - # ## Вставка элемента num по индексу index в массив ### - def insert(nums, num, index) - # Сдвинуть элемент с индексом index и все последующие элементы на одну позицию назад - for i in (nums.length - 1).downto(index + 1) - nums[i] = nums[i - 1] - end - - # Присвоить num элементу по индексу index - nums[index] = num - end - - - # ## Удаление элемента по индексу index ### - def remove(nums, index) - # Сдвинуть все элементы после индекса index на одну позицию вперед - for i in index...(nums.length - 1) - nums[i] = nums[i + 1] - end - end - - # ## Обход массива ### - def traverse(nums) - count = 0 - - # Обход массива по индексам - for i in 0...nums.length - count += nums[i] - end - - # Непосредственно обходить элементы массива - for num in nums - count += num - end - end - - # ## Поиск заданного элемента в массиве ### + ### Поиск заданного элемента в массиве ### def find(nums, target) for i in 0...nums.length return i if nums[i] == target @@ -1526,23 +1325,7 @@ comments: true === "Ruby" ```ruby title="array.rb" - =begin - File: array.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Случайный доступ к элементу ### - def random_access(nums) - # Случайным образом выбрать число из интервала [0, nums.length) - random_index = Random.rand(0...nums.length) - - # Получить и вернуть случайный элемент - nums[random_index] - end - - - # ## Увеличить длину массива ### + ### Увеличить длину массива ### # Обратите внимание: Array в Ruby является динамическим массивом и может быть расширен напрямую # Для удобства обучения эта функция рассматривает Array как массив неизменяемой длины def extend(nums, enlarge) diff --git a/ru/docs/chapter_array_and_linkedlist/linked_list.md b/ru/docs/chapter_array_and_linkedlist/linked_list.md index 79024bf97..10355d5d5 100644 --- a/ru/docs/chapter_array_and_linkedlist/linked_list.md +++ b/ru/docs/chapter_array_and_linkedlist/linked_list.md @@ -570,16 +570,7 @@ comments: true === "Ruby" ```ruby title="linked_list.rb" - =begin - File: linked_list.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/print_util' - - # ## Вставка узла _p после узла n0 в связном списке ### + ### Вставка узла _p после узла n0 в связном списке ### # В Ruby `p` — встроенная функция, а `P` — константа, поэтому вместо этого можно использовать `_p` def insert(n0, _p) n1 = n0.next @@ -780,24 +771,7 @@ comments: true === "Ruby" ```ruby title="linked_list.rb" - =begin - File: linked_list.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/print_util' - - # ## Вставка узла _p после узла n0 в связном списке ### - # В Ruby `p` — встроенная функция, а `P` — константа, поэтому вместо этого можно использовать `_p` - def insert(n0, _p) - n1 = n0.next - _p.next = n1 - n0.next = _p - end - - # ## Удаление первого узла после узла n0 в связном списке ### + ### Удаление первого узла после узла n0 в связном списке ### def remove(n0) return if n0.next.nil? @@ -1001,34 +975,7 @@ comments: true === "Ruby" ```ruby title="linked_list.rb" - =begin - File: linked_list.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/print_util' - - # ## Вставка узла _p после узла n0 в связном списке ### - # В Ruby `p` — встроенная функция, а `P` — константа, поэтому вместо этого можно использовать `_p` - def insert(n0, _p) - n1 = n0.next - _p.next = n1 - n0.next = _p - end - - # ## Удаление первого узла после узла n0 в связном списке ### - def remove(n0) - return if n0.next.nil? - - # n0 -> remove_node -> n1 - remove_node = n0.next - n1 = remove_node.next - n0.next = n1 - end - - # ## Доступ к узлу связного списка по индексу index ### + ### Доступ к узлу связного списка по индексу index ### def access(head, index) for i in 0...index return nil if head.nil? @@ -1252,44 +1199,7 @@ comments: true === "Ruby" ```ruby title="linked_list.rb" - =begin - File: linked_list.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/print_util' - - # ## Вставка узла _p после узла n0 в связном списке ### - # В Ruby `p` — встроенная функция, а `P` — константа, поэтому вместо этого можно использовать `_p` - def insert(n0, _p) - n1 = n0.next - _p.next = n1 - n0.next = _p - end - - # ## Удаление первого узла после узла n0 в связном списке ### - def remove(n0) - return if n0.next.nil? - - # n0 -> remove_node -> n1 - remove_node = n0.next - n1 = remove_node.next - n0.next = n1 - end - - # ## Доступ к узлу связного списка по индексу index ### - def access(head, index) - for i in 0...index - return nil if head.nil? - head = head.next - end - - head - end - - # ## Поиск первого узла со значением target в связном списке ### + ### Поиск первого узла со значением target в связном списке ### def find(head, target) index = 0 while head diff --git a/ru/docs/chapter_array_and_linkedlist/list.md b/ru/docs/chapter_array_and_linkedlist/list.md index 0ae011b67..c0fd0f5ad 100644 --- a/ru/docs/chapter_array_and_linkedlist/list.md +++ b/ru/docs/chapter_array_and_linkedlist/list.md @@ -2198,18 +2198,12 @@ comments: true === "Ruby" ```ruby title="my_list.rb" - =begin - File: my_list.rb - Created Time: 2024-03-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Класс списка ### + ### Класс списка ### class MyList attr_reader :size # Получить длину списка (текущее число элементов) attr_reader :capacity # Получить вместимость списка - # ## Конструктор ### + ### Конструктор ### def initialize @capacity = 10 @size = 0 @@ -2217,20 +2211,20 @@ comments: true @arr = Array.new(capacity) end - # ## Доступ к элементу ### + ### Доступ к элементу ### def get(index) # Если индекс выходит за границы, выбрасывается исключение; далее аналогично raise IndexError, "индекс выходит за границы" if index < 0 || index >= size @arr[index] end - # ## Доступ к элементу ### + ### Доступ к элементу ### def set(index, num) raise IndexError, "индекс выходит за границы" if index < 0 || index >= size @arr[index] = num end - # ## Добавление элемента в конец ### + ### Добавление элемента в конец ### def add(num) # При превышении вместимости по числу элементов запускается расширение extend_capacity if size == capacity @@ -2240,7 +2234,7 @@ comments: true @size += 1 end - # ## Вставка элемента в середину ### + ### Вставка элемента в середину ### def insert(index, num) raise IndexError, "индекс выходит за границы" if index < 0 || index >= size @@ -2257,7 +2251,7 @@ comments: true @size += 1 end - # ## Удаление элемента ### + ### Удаление элемента ### def remove(index) raise IndexError, "индекс выходит за границы" if index < 0 || index >= size num = @arr[index] @@ -2274,7 +2268,7 @@ comments: true num end - # ## Расширение списка ### + ### Расширение списка ### def extend_capacity # Создать новый массив длиной в extend_ratio раз больше исходного и скопировать в него исходный массив arr = @arr.dup + Array.new(capacity * (@extend_ratio - 1)) @@ -2282,7 +2276,7 @@ comments: true @capacity = arr.length end - # ## Преобразование списка в массив ### + ### Преобразование списка в массив ### def to_array sz = size # Преобразовывать только элементы списка в пределах фактической длины diff --git a/ru/docs/chapter_backtracking/backtracking_algorithm.md b/ru/docs/chapter_backtracking/backtracking_algorithm.md index 5e296b9ee..61e56658f 100644 --- a/ru/docs/chapter_backtracking/backtracking_algorithm.md +++ b/ru/docs/chapter_backtracking/backtracking_algorithm.md @@ -220,16 +220,7 @@ comments: true === "Ruby" ```ruby title="preorder_traversal_i_compact.rb" - =begin - File: preorder_traversal_i_compact.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Предварительный обход: пример 1 ### + ### Предварительный обход: пример 1 ### def pre_order(root) return unless root @@ -534,16 +525,7 @@ comments: true === "Ruby" ```ruby title="preorder_traversal_ii_compact.rb" - =begin - File: preorder_traversal_ii_compact.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Предварительный обход: пример 2 ### + ### Предварительный обход: пример 2 ### def pre_order(root) return unless root @@ -896,16 +878,7 @@ comments: true === "Ruby" ```ruby title="preorder_traversal_iii_compact.rb" - =begin - File: preorder_traversal_iii_compact.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Предварительный обход: пример 3 ### + ### Предварительный обход: пример 3 ### def pre_order(root) # Отсечение return if !root || root.val == 3 @@ -1906,161 +1879,32 @@ comments: true === "Ruby" ```ruby title="preorder_traversal_iii_template.rb" - =begin - File: preorder_traversal_iii_template.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Проверка, является ли текущее состояние решением ### + ### Проверка, является ли текущее состояние решением ### def is_solution?(state) !state.empty? && state.last.val == 7 end - =begin - File: preorder_traversal_iii_template.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Проверка, является ли текущее состояние решением ### - def is_solution?(state) - !state.empty? && state.last.val == 7 - end - - # ## Записать решение ### + ### Записать решение ### def record_solution(state, res) res << state.dup end - =begin - File: preorder_traversal_iii_template.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Проверка, является ли текущее состояние решением ### - def is_solution?(state) - !state.empty? && state.last.val == 7 - end - - # ## Записать решение ### - def record_solution(state, res) - res << state.dup - end - - # ## Проверка допустимости этого выбора в текущем состоянии ### + ### Проверка допустимости этого выбора в текущем состоянии ### def is_valid?(state, choice) choice && choice.val != 3 end - =begin - File: preorder_traversal_iii_template.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Проверка, является ли текущее состояние решением ### - def is_solution?(state) - !state.empty? && state.last.val == 7 - end - - # ## Записать решение ### - def record_solution(state, res) - res << state.dup - end - - # ## Проверка допустимости этого выбора в текущем состоянии ### - def is_valid?(state, choice) - choice && choice.val != 3 - end - - # ## Обновить состояние ### + ### Обновить состояние ### def make_choice(state, choice) state << choice end - =begin - File: preorder_traversal_iii_template.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Проверка, является ли текущее состояние решением ### - def is_solution?(state) - !state.empty? && state.last.val == 7 - end - - # ## Записать решение ### - def record_solution(state, res) - res << state.dup - end - - # ## Проверка допустимости этого выбора в текущем состоянии ### - def is_valid?(state, choice) - choice && choice.val != 3 - end - - # ## Обновить состояние ### - def make_choice(state, choice) - state << choice - end - - # ## Восстановить состояние ### + ### Восстановить состояние ### def undo_choice(state, choice) state.pop end - =begin - File: preorder_traversal_iii_template.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Проверка, является ли текущее состояние решением ### - def is_solution?(state) - !state.empty? && state.last.val == 7 - end - - # ## Записать решение ### - def record_solution(state, res) - res << state.dup - end - - # ## Проверка допустимости этого выбора в текущем состоянии ### - def is_valid?(state, choice) - choice && choice.val != 3 - end - - # ## Обновить состояние ### - def make_choice(state, choice) - state << choice - end - - # ## Восстановить состояние ### - def undo_choice(state, choice) - state.pop - end - - # ## Алгоритм бэктрекинга: пример 3 ### + ### Алгоритм бэктрекинга: пример 3 ### def backtrack(state, choices, res) # Проверить, является ли текущее состояние решением record_solution(state, res) if is_solution?(state) diff --git a/ru/docs/chapter_backtracking/n_queens_problem.md b/ru/docs/chapter_backtracking/n_queens_problem.md index 4b8c53888..422a45f5a 100644 --- a/ru/docs/chapter_backtracking/n_queens_problem.md +++ b/ru/docs/chapter_backtracking/n_queens_problem.md @@ -703,13 +703,7 @@ comments: true === "Ruby" ```ruby title="n_queens.rb" - =begin - File: n_queens.rb - Created Time: 2024-05-21 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: n ферзей ### + ### Алгоритм бэктрекинга: n ферзей ### def backtrack(row, n, state, res, cols, diags1, diags2) # Когда все строки уже обработаны, записать решение if row == n @@ -736,40 +730,7 @@ comments: true end end - =begin - File: n_queens.rb - Created Time: 2024-05-21 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: n ферзей ### - def backtrack(row, n, state, res, cols, diags1, diags2) - # Когда все строки уже обработаны, записать решение - if row == n - res << state.map { |row| row.dup } - return - end - - # Обойти все столбцы - for col in 0...n - # Вычислить главную и побочную диагонали, соответствующие этой клетке - diag1 = row - col + n - 1 - 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 - end - end - end - - # ## Решить задачу о n ферзях ### + ### Решить задачу о n ферзях ### def n_queens(n) # Инициализировать доску размера n*n, где 'Q' обозначает ферзя, а '#' — пустую клетку state = Array.new(n) { Array.new(n, "#") } diff --git a/ru/docs/chapter_backtracking/permutations_problem.md b/ru/docs/chapter_backtracking/permutations_problem.md index aba8f0894..e49eaced7 100644 --- a/ru/docs/chapter_backtracking/permutations_problem.md +++ b/ru/docs/chapter_backtracking/permutations_problem.md @@ -506,13 +506,7 @@ comments: true === "Ruby" ```ruby title="permutations_i.rb" - =begin - File: permutations_i.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: все перестановки I ### + ### Алгоритм бэктрекинга: все перестановки I ### def backtrack(state, choices, selected, res) # Когда длина состояния равна числу элементов, записать решение if state.length == choices.length @@ -536,37 +530,7 @@ comments: true end end - =begin - File: permutations_i.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: все перестановки I ### - def backtrack(state, choices, selected, res) - # Когда длина состояния равна числу элементов, записать решение - if state.length == choices.length - res << state.dup - return - end - - # Перебор всех вариантов выбора - choices.each_with_index do |choice, i| - # Отсечение: нельзя выбирать один и тот же элемент повторно - unless selected[i] - # Попытка: сделать выбор и обновить состояние - selected[i] = true - state << choice - # Перейти к следующему выбору - backtrack(state, choices, selected, res) - # Откат: отменить выбор и восстановить предыдущее состояние - selected[i] = false - state.pop - end - end - end - - # ## Все перестановки I ### + ### Все перестановки I ### def permutations_i(nums) res = [] backtrack([], nums, Array.new(nums.length, false), res) @@ -1087,13 +1051,7 @@ comments: true === "Ruby" ```ruby title="permutations_ii.rb" - =begin - File: permutations_ii.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: все перестановки II ### + ### Алгоритм бэктрекинга: все перестановки II ### def backtrack(state, choices, selected, res) # Когда длина состояния равна числу элементов, записать решение if state.length == choices.length @@ -1119,39 +1077,7 @@ comments: true end end - =begin - File: permutations_ii.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: все перестановки II ### - def backtrack(state, choices, selected, res) - # Когда длина состояния равна числу элементов, записать решение - if state.length == choices.length - res << state.dup - return - end - - # Перебор всех вариантов выбора - duplicated = Set.new - choices.each_with_index do |choice, i| - # Отсечение: нельзя выбирать один и тот же элемент повторно и нельзя повторно выбирать равные элементы - if !selected[i] && !duplicated.include?(choice) - # Попытка: сделать выбор и обновить состояние - duplicated.add(choice) - selected[i] = true - state << choice - # Перейти к следующему выбору - backtrack(state, choices, selected, res) - # Откат: отменить выбор и восстановить предыдущее состояние - selected[i] = false - state.pop - end - end - end - - # ## Все перестановки II ### + ### Все перестановки II ### def permutations_ii(nums) res = [] backtrack([], nums, Array.new(nums.length, false), res) diff --git a/ru/docs/chapter_backtracking/subset_sum_problem.md b/ru/docs/chapter_backtracking/subset_sum_problem.md index c824eae20..10c822f41 100644 --- a/ru/docs/chapter_backtracking/subset_sum_problem.md +++ b/ru/docs/chapter_backtracking/subset_sum_problem.md @@ -470,13 +470,7 @@ comments: true === "Ruby" ```ruby title="subset_sum_i_naive.rb" - =begin - File: subset_sum_i_naive.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: сумма подмножеств I ### + ### Алгоритм бэктрекинга: сумма подмножеств I ### def backtrack(state, target, total, choices, res) # Если сумма подмножества равна target, записать решение if total == target @@ -497,34 +491,7 @@ comments: true end end - =begin - File: subset_sum_i_naive.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: сумма подмножеств I ### - def backtrack(state, target, total, choices, res) - # Если сумма подмножества равна target, записать решение - if total == target - res << state.dup - return - end - - # Перебор всех вариантов выбора - for i in 0...choices.length - # Отсечение: если сумма подмножества превышает target, пропустить этот выбор - next if total + choices[i] > target - # Попытка: сделать выбор и обновить элемент и total - state << choices[i] - # Перейти к следующему выбору - backtrack(state, target, total + choices[i], choices, res) - # Откат: отменить выбор и восстановить предыдущее состояние - state.pop - end - end - - # ## Решить задачу суммы подмножеств I (с повторяющимися подмножествами) ### + ### Решить задачу суммы подмножеств I (с повторяющимися подмножествами) ### def subset_sum_i_naive(nums, target) state = [] # Состояние (подмножество) total = 0 # Сумма подмножеств @@ -1062,13 +1029,7 @@ comments: true === "Ruby" ```ruby title="subset_sum_i.rb" - =begin - File: subset_sum_i.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: сумма подмножеств I ### + ### Алгоритм бэктрекинга: сумма подмножеств I ### def backtrack(state, target, choices, start, res) # Если сумма подмножества равна target, записать решение if target.zero? @@ -1090,35 +1051,7 @@ comments: true end end - =begin - File: subset_sum_i.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: сумма подмножеств I ### - def backtrack(state, target, choices, start, res) - # Если сумма подмножества равна target, записать решение - if target.zero? - res << state.dup - return - end - # Обойти все варианты выбора - # Отсечение 2: начинать обход с start, чтобы избежать генерации повторяющихся подмножеств - for i in start...choices.length - # Отсечение 1: если сумма подмножества превышает target, немедленно завершить цикл - # Это связано с тем, что массив уже отсортирован, следующие элементы больше, и сумма подмножества точно превысит target - break if target - choices[i] < 0 - # Попытка: сделать выбор и обновить target и start - state << choices[i] - # Перейти к следующему выбору - backtrack(state, target - choices[i], choices, i, res) - # Откат: отменить выбор и восстановить предыдущее состояние - state.pop - end - end - - # ## Решить задачу суммы подмножеств I ### + ### Решить задачу суммы подмножеств I ### def subset_sum_i(nums, target) state = [] # Состояние (подмножество) nums.sort! # Отсортировать nums @@ -1703,13 +1636,7 @@ comments: true === "Ruby" ```ruby title="subset_sum_ii.rb" - =begin - File: subset_sum_ii.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: сумма подмножеств II ### + ### Алгоритм бэктрекинга: сумма подмножеств II ### def backtrack(state, target, choices, start, res) # Если сумма подмножества равна target, записать решение if target.zero? @@ -1735,39 +1662,7 @@ comments: true end end - =begin - File: subset_sum_ii.rb - Created Time: 2024-05-22 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Алгоритм бэктрекинга: сумма подмножеств II ### - def backtrack(state, target, choices, start, res) - # Если сумма подмножества равна target, записать решение - if target.zero? - res << state.dup - return - end - - # Обойти все варианты выбора - # Отсечение 2: начинать обход с start, чтобы избежать генерации повторяющихся подмножеств - # Отсечение 3: начинать обход с start, чтобы избежать повторного выбора одного и того же элемента - for i in start...choices.length - # Отсечение 1: если сумма подмножества превышает target, немедленно завершить цикл - # Это связано с тем, что массив уже отсортирован, следующие элементы больше, и сумма подмножества точно превысит target - break if target - choices[i] < 0 - # Отсечение 4: если этот элемент равен элементу слева, значит ветвь поиска повторяется, ее нужно сразу пропустить - next if i > start && choices[i] == choices[i - 1] - # Попытка: сделать выбор и обновить target и start - state << choices[i] - # Перейти к следующему выбору - backtrack(state, target - choices[i], choices, i + 1, res) - # Откат: отменить выбор и восстановить предыдущее состояние - state.pop - end - end - - # ## Решить задачу суммы подмножеств II ### + ### Решить задачу суммы подмножеств II ### def subset_sum_ii(nums, target) state = [] # Состояние (подмножество) nums.sort! # Отсортировать nums diff --git a/ru/docs/chapter_computational_complexity/iteration_and_recursion.md b/ru/docs/chapter_computational_complexity/iteration_and_recursion.md index f68f2cc6d..5b9a0747f 100644 --- a/ru/docs/chapter_computational_complexity/iteration_and_recursion.md +++ b/ru/docs/chapter_computational_complexity/iteration_and_recursion.md @@ -185,13 +185,7 @@ comments: true === "Ruby" ```ruby title="iteration.rb" - =begin - File: iteration.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com), Cy (9738314@gmail.com) - =end - - # ## Цикл for ### + ### Цикл for ### def for_loop(n) res = 0 @@ -419,25 +413,7 @@ comments: true === "Ruby" ```ruby title="iteration.rb" - =begin - File: iteration.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com), Cy (9738314@gmail.com) - =end - - # ## Цикл for ### - def for_loop(n) - res = 0 - - # Циклическое суммирование 1, 2, ..., n-1, n - for i in 1..n - res += i - end - - res - end - - # ## Цикл while ### + ### Цикл while ### def while_loop(n) res = 0 i = 1 # Инициализация условной переменной @@ -680,39 +656,7 @@ comments: true === "Ruby" ```ruby title="iteration.rb" - =begin - File: iteration.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com), Cy (9738314@gmail.com) - =end - - # ## Цикл for ### - def for_loop(n) - res = 0 - - # Циклическое суммирование 1, 2, ..., n-1, n - for i in 1..n - res += i - end - - res - end - - # ## Цикл while ### - def while_loop(n) - res = 0 - i = 1 # Инициализация условной переменной - - # Циклическое суммирование 1, 2, ..., n-1, n - while i <= n - res += i - i += 1 # Обновить условную переменную - end - - res - end - - # ## Цикл while (двойное обновление) ### + ### Цикл while (двойное обновление) ### def while_loop_ii(n) res = 0 i = 1 # Инициализация условной переменной @@ -948,55 +892,7 @@ comments: true === "Ruby" ```ruby title="iteration.rb" - =begin - File: iteration.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com), Cy (9738314@gmail.com) - =end - - # ## Цикл for ### - def for_loop(n) - res = 0 - - # Циклическое суммирование 1, 2, ..., n-1, n - for i in 1..n - res += i - end - - res - end - - # ## Цикл while ### - def while_loop(n) - res = 0 - i = 1 # Инициализация условной переменной - - # Циклическое суммирование 1, 2, ..., n-1, n - while i <= n - res += i - i += 1 # Обновить условную переменную - end - - res - end - - # ## Цикл while (двойное обновление) ### - def while_loop_ii(n) - res = 0 - i = 1 # Инициализация условной переменной - - # Циклическое суммирование 1, 4, 10, ... - while i <= n - res += i - # Обновить условную переменную - i += 1 - i *= 2 - end - - res - end - - # ## Двойной цикл for ### + ### Двойной цикл for ### def nested_for_loop(n) res = "" @@ -1224,13 +1120,7 @@ comments: true === "Ruby" ```ruby title="recursion.rb" - =begin - File: recursion.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Рекурсия ### + ### Рекурсия ### def recur(n) # Условие завершения return 1 if n == 1 @@ -1445,43 +1335,7 @@ comments: true === "Ruby" ```ruby title="recursion.rb" - =begin - File: recursion.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Рекурсия ### - def recur(n) - # Условие завершения - return 1 if n == 1 - # Рекурсия: рекурсивный вызов - res = recur(n - 1) - # Возврат: вернуть результат - n + res - end - - # ## Имитация рекурсии итерацией ### - def for_loop_recur(n) - # Использовать явный стек для имитации системного стека вызовов - stack = [] - res = 0 - - # Рекурсия: рекурсивный вызов - for i in n.downto(0) - # Имитировать «рекурсию» с помощью операции помещения в стек - stack << i - end - # Возврат: вернуть результат - while !stack.empty? - res += stack.pop - end - - # res = 1+2+3+...+n - res - end - - # ## Хвостовая рекурсия ### + ### Хвостовая рекурсия ### def tail_recur(n, res) # Условие завершения return res if n == 0 @@ -1705,51 +1559,7 @@ comments: true === "Ruby" ```ruby title="recursion.rb" - =begin - File: recursion.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Рекурсия ### - def recur(n) - # Условие завершения - return 1 if n == 1 - # Рекурсия: рекурсивный вызов - res = recur(n - 1) - # Возврат: вернуть результат - n + res - end - - # ## Имитация рекурсии итерацией ### - def for_loop_recur(n) - # Использовать явный стек для имитации системного стека вызовов - stack = [] - res = 0 - - # Рекурсия: рекурсивный вызов - for i in n.downto(0) - # Имитировать «рекурсию» с помощью операции помещения в стек - stack << i - end - # Возврат: вернуть результат - while !stack.empty? - res += stack.pop - end - - # res = 1+2+3+...+n - res - end - - # ## Хвостовая рекурсия ### - def tail_recur(n, res) - # Условие завершения - return res if n == 0 - # Хвостовой рекурсивный вызов - tail_recur(n - 1, res + n) - end - - # ## Последовательность Фибоначчи: рекурсия ### + ### Последовательность Фибоначчи: рекурсия ### def fib(n) # Условие завершения: f(1) = 0, f(2) = 1 return n - 1 if n == 1 || n == 2 @@ -2084,23 +1894,7 @@ comments: true === "Ruby" ```ruby title="recursion.rb" - =begin - File: recursion.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Рекурсия ### - def recur(n) - # Условие завершения - return 1 if n == 1 - # Рекурсия: рекурсивный вызов - res = recur(n - 1) - # Возврат: вернуть результат - n + res - end - - # ## Имитация рекурсии итерацией ### + ### Имитация рекурсии итерацией ### def for_loop_recur(n) # Использовать явный стек для имитации системного стека вызовов stack = [] diff --git a/ru/docs/chapter_computational_complexity/space_complexity.md b/ru/docs/chapter_computational_complexity/space_complexity.md index d28ecca7a..c99ba724c 100644 --- a/ru/docs/chapter_computational_complexity/space_complexity.md +++ b/ru/docs/chapter_computational_complexity/space_complexity.md @@ -1157,39 +1157,13 @@ $$ === "Ruby" ```ruby title="space_complexity.rb" - =begin - File: space_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Функция ### + ### Функция ### def function # Выполнить некоторые операции 0 end - =begin - File: space_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Функция ### - def function - # Выполнить некоторые операции - 0 - end - - # ## Постоянная сложность ### + ### Постоянная сложность ### def constant(n) # Константы, переменные и объекты занимают O(1) памяти a = 0 @@ -1468,36 +1442,7 @@ $$ === "Ruby" ```ruby title="space_complexity.rb" - =begin - File: space_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Функция ### - def function - # Выполнить некоторые операции - 0 - end - - # ## Постоянная сложность ### - def constant(n) - # Константы, переменные и объекты занимают O(1) памяти - a = 0 - nums = [0] * 10000 - node = ListNode.new - - # Переменные в цикле занимают O(1) памяти - (0...n).each { c = 0 } - # Функции в цикле занимают O(1) памяти - (0...n).each { function } - end - - # ## Линейная сложность ### + ### Линейная сложность ### def linear(n) # Список длины n занимает O(n) памяти nums = Array.new(n, 0) @@ -1662,48 +1607,7 @@ $$ === "Ruby" ```ruby title="space_complexity.rb" - =begin - File: space_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Функция ### - def function - # Выполнить некоторые операции - 0 - end - - # ## Постоянная сложность ### - def constant(n) - # Константы, переменные и объекты занимают O(1) памяти - a = 0 - nums = [0] * 10000 - node = ListNode.new - - # Переменные в цикле занимают O(1) памяти - (0...n).each { c = 0 } - # Функции в цикле занимают O(1) памяти - (0...n).each { function } - end - - # ## Линейная сложность ### - def linear(n) - # Список длины n занимает O(n) памяти - nums = Array.new(n, 0) - - # Хеш-таблица длины n занимает O(n) памяти - hmap = {} - for i in 0...n - hmap[i] = i.to_s - end - end - - # ## Линейная сложность (рекурсивная реализация) ### + ### Линейная сложность (рекурсивная реализация) ### def linear_recur(n) puts "Рекурсия n = #{n}" return if n == 1 @@ -1937,55 +1841,7 @@ $$ === "Ruby" ```ruby title="space_complexity.rb" - =begin - File: space_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Функция ### - def function - # Выполнить некоторые операции - 0 - end - - # ## Постоянная сложность ### - def constant(n) - # Константы, переменные и объекты занимают O(1) памяти - a = 0 - nums = [0] * 10000 - node = ListNode.new - - # Переменные в цикле занимают O(1) памяти - (0...n).each { c = 0 } - # Функции в цикле занимают O(1) памяти - (0...n).each { function } - end - - # ## Линейная сложность ### - def linear(n) - # Список длины n занимает O(n) памяти - nums = Array.new(n, 0) - - # Хеш-таблица длины n занимает O(n) памяти - hmap = {} - for i in 0...n - hmap[i] = i.to_s - end - end - - # ## Линейная сложность (рекурсивная реализация) ### - def linear_recur(n) - puts "Рекурсия n = #{n}" - return if n == 1 - linear_recur(n - 1) - end - - # ## Квадратичная сложность ### + ### Квадратичная сложность ### def quadratic(n) # Двумерный список занимает O(n^2) памяти Array.new(n) { Array.new(n, 0) } @@ -2163,61 +2019,7 @@ $$ === "Ruby" ```ruby title="space_complexity.rb" - =begin - File: space_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Функция ### - def function - # Выполнить некоторые операции - 0 - end - - # ## Постоянная сложность ### - def constant(n) - # Константы, переменные и объекты занимают O(1) памяти - a = 0 - nums = [0] * 10000 - node = ListNode.new - - # Переменные в цикле занимают O(1) памяти - (0...n).each { c = 0 } - # Функции в цикле занимают O(1) памяти - (0...n).each { function } - end - - # ## Линейная сложность ### - def linear(n) - # Список длины n занимает O(n) памяти - nums = Array.new(n, 0) - - # Хеш-таблица длины n занимает O(n) памяти - hmap = {} - for i in 0...n - hmap[i] = i.to_s - end - end - - # ## Линейная сложность (рекурсивная реализация) ### - def linear_recur(n) - puts "Рекурсия n = #{n}" - return if n == 1 - linear_recur(n - 1) - end - - # ## Квадратичная сложность ### - def quadratic(n) - # Двумерный список занимает O(n^2) памяти - Array.new(n) { Array.new(n, 0) } - end - - # ## Квадратичная сложность (рекурсивная реализация) ### + ### Квадратичная сложность (рекурсивная реализация) ### def quadratic_recur(n) return 0 unless n > 0 @@ -2410,70 +2212,7 @@ $$ === "Ruby" ```ruby title="space_complexity.rb" - =begin - File: space_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Функция ### - def function - # Выполнить некоторые операции - 0 - end - - # ## Постоянная сложность ### - def constant(n) - # Константы, переменные и объекты занимают O(1) памяти - a = 0 - nums = [0] * 10000 - node = ListNode.new - - # Переменные в цикле занимают O(1) памяти - (0...n).each { c = 0 } - # Функции в цикле занимают O(1) памяти - (0...n).each { function } - end - - # ## Линейная сложность ### - def linear(n) - # Список длины n занимает O(n) памяти - nums = Array.new(n, 0) - - # Хеш-таблица длины n занимает O(n) памяти - hmap = {} - for i in 0...n - hmap[i] = i.to_s - end - end - - # ## Линейная сложность (рекурсивная реализация) ### - def linear_recur(n) - puts "Рекурсия n = #{n}" - return if n == 1 - linear_recur(n - 1) - end - - # ## Квадратичная сложность ### - def quadratic(n) - # Двумерный список занимает O(n^2) памяти - Array.new(n) { Array.new(n, 0) } - end - - # ## Квадратичная сложность (рекурсивная реализация) ### - def quadratic_recur(n) - return 0 unless n > 0 - - # Длина массива nums равна n, n-1, ..., 2, 1 - nums = Array.new(n, 0) - quadratic_recur(n - 1) - end - - # ## Экспоненциальная сложность (построение полного двоичного дерева) ### + ### Экспоненциальная сложность (построение полного двоичного дерева) ### def build_tree(n) return if n == 0 diff --git a/ru/docs/chapter_computational_complexity/time_complexity.md b/ru/docs/chapter_computational_complexity/time_complexity.md index d2acc92af..683106360 100644 --- a/ru/docs/chapter_computational_complexity/time_complexity.md +++ b/ru/docs/chapter_computational_complexity/time_complexity.md @@ -1182,13 +1182,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### + ### Постоянная сложность ### def constant(n) count = 0 size = 100000 @@ -1357,23 +1351,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### + ### Линейная сложность ### def linear(n) count = 0 (0...n).each { count += 1 } @@ -1557,30 +1535,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### + ### Линейная сложность (обход массива) ### def array_traversal(nums) count = 0 @@ -1796,42 +1751,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### - def array_traversal(nums) - count = 0 - - # Число итераций пропорционально длине массива - for num in nums - count += 1 - end - - count - end - - # ## Квадратичная сложность ### + ### Квадратичная сложность ### def quadratic(n) count = 0 @@ -2133,56 +2053,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### - def array_traversal(nums) - count = 0 - - # Число итераций пропорционально длине массива - for num in nums - count += 1 - end - - count - end - - # ## Квадратичная сложность ### - def quadratic(n) - count = 0 - - # Число итераций квадратично зависит от размера данных n - for i in 0...n - for j in 0...n - count += 1 - end - end - - count - end - - # ## Квадратичная сложность (пузырьковая сортировка) ### + ### Квадратичная сложность (пузырьковая сортировка) ### def bubble_sort(nums) count = 0 # Счетчик @@ -2438,77 +2309,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### - def array_traversal(nums) - count = 0 - - # Число итераций пропорционально длине массива - for num in nums - count += 1 - end - - count - end - - # ## Квадратичная сложность ### - def quadratic(n) - count = 0 - - # Число итераций квадратично зависит от размера данных n - for i in 0...n - for j in 0...n - count += 1 - end - end - - count - end - - # ## Квадратичная сложность (пузырьковая сортировка) ### - def bubble_sort(nums) - count = 0 # Счетчик - - # Внешний цикл: неотсортированный диапазон [0, i] - for i in (nums.length - 1).downto(0) - # Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец - for j in 0...i - if nums[j] > nums[j + 1] - # Поменять местами nums[j] и nums[j + 1] - tmp = nums[j] - nums[j] = nums[j + 1] - nums[j + 1] = tmp - count += 3 # Обмен элементов включает 3 элементарные операции - end - end - end - - count - end - - # ## Экспоненциальная сложность (итеративная реализация) ### + ### Экспоненциальная сложность (итеративная реализация) ### def exponential(n) count, base = 0, 1 @@ -2668,91 +2469,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### - def array_traversal(nums) - count = 0 - - # Число итераций пропорционально длине массива - for num in nums - count += 1 - end - - count - end - - # ## Квадратичная сложность ### - def quadratic(n) - count = 0 - - # Число итераций квадратично зависит от размера данных n - for i in 0...n - for j in 0...n - count += 1 - end - end - - count - end - - # ## Квадратичная сложность (пузырьковая сортировка) ### - def bubble_sort(nums) - count = 0 # Счетчик - - # Внешний цикл: неотсортированный диапазон [0, i] - for i in (nums.length - 1).downto(0) - # Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец - for j in 0...i - if nums[j] > nums[j + 1] - # Поменять местами nums[j] и nums[j + 1] - tmp = nums[j] - nums[j] = nums[j + 1] - nums[j + 1] = tmp - count += 3 # Обмен элементов включает 3 элементарные операции - end - end - end - - count - end - - # ## Экспоненциальная сложность (итеративная реализация) ### - def exponential(n) - count, base = 0, 1 - - # На каждом шаге клетка делится надвое, образуя последовательность 1, 2, 4, 8, ..., 2^(n-1) - (0...n).each do - (0...base).each { count += 1 } - base *= 2 - end - - # count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 - count - end - - # ## Экспоненциальная сложность (рекурсивная реализация) ### + ### Экспоненциальная сложность (рекурсивная реализация) ### def exp_recur(n) return 1 if n == 1 exp_recur(n - 1) + exp_recur(n - 1) + 1 @@ -2943,97 +2660,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### - def array_traversal(nums) - count = 0 - - # Число итераций пропорционально длине массива - for num in nums - count += 1 - end - - count - end - - # ## Квадратичная сложность ### - def quadratic(n) - count = 0 - - # Число итераций квадратично зависит от размера данных n - for i in 0...n - for j in 0...n - count += 1 - end - end - - count - end - - # ## Квадратичная сложность (пузырьковая сортировка) ### - def bubble_sort(nums) - count = 0 # Счетчик - - # Внешний цикл: неотсортированный диапазон [0, i] - for i in (nums.length - 1).downto(0) - # Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец - for j in 0...i - if nums[j] > nums[j + 1] - # Поменять местами nums[j] и nums[j + 1] - tmp = nums[j] - nums[j] = nums[j + 1] - nums[j + 1] = tmp - count += 3 # Обмен элементов включает 3 элементарные операции - end - end - end - - count - end - - # ## Экспоненциальная сложность (итеративная реализация) ### - def exponential(n) - count, base = 0, 1 - - # На каждом шаге клетка делится надвое, образуя последовательность 1, 2, 4, 8, ..., 2^(n-1) - (0...n).each do - (0...base).each { count += 1 } - base *= 2 - end - - # count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 - count - end - - # ## Экспоненциальная сложность (рекурсивная реализация) ### - def exp_recur(n) - return 1 if n == 1 - exp_recur(n - 1) + exp_recur(n - 1) + 1 - end - - # ## Логарифмическая сложность (итеративная реализация) ### + ### Логарифмическая сложность (итеративная реализация) ### def logarithmic(n) count = 0 @@ -3190,109 +2817,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### - def array_traversal(nums) - count = 0 - - # Число итераций пропорционально длине массива - for num in nums - count += 1 - end - - count - end - - # ## Квадратичная сложность ### - def quadratic(n) - count = 0 - - # Число итераций квадратично зависит от размера данных n - for i in 0...n - for j in 0...n - count += 1 - end - end - - count - end - - # ## Квадратичная сложность (пузырьковая сортировка) ### - def bubble_sort(nums) - count = 0 # Счетчик - - # Внешний цикл: неотсортированный диапазон [0, i] - for i in (nums.length - 1).downto(0) - # Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец - for j in 0...i - if nums[j] > nums[j + 1] - # Поменять местами nums[j] и nums[j + 1] - tmp = nums[j] - nums[j] = nums[j + 1] - nums[j + 1] = tmp - count += 3 # Обмен элементов включает 3 элементарные операции - end - end - end - - count - end - - # ## Экспоненциальная сложность (итеративная реализация) ### - def exponential(n) - count, base = 0, 1 - - # На каждом шаге клетка делится надвое, образуя последовательность 1, 2, 4, 8, ..., 2^(n-1) - (0...n).each do - (0...base).each { count += 1 } - base *= 2 - end - - # count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 - count - end - - # ## Экспоненциальная сложность (рекурсивная реализация) ### - def exp_recur(n) - return 1 if n == 1 - exp_recur(n - 1) + exp_recur(n - 1) + 1 - end - - # ## Логарифмическая сложность (итеративная реализация) ### - def logarithmic(n) - count = 0 - - while n > 1 - n /= 2 - count += 1 - end - - count - end - - # ## Логарифмическая сложность (рекурсивная реализация) ### + ### Логарифмическая сложность (рекурсивная реализация) ### def log_recur(n) return 0 unless n > 1 log_recur(n / 2) + 1 @@ -3502,115 +3027,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### - def array_traversal(nums) - count = 0 - - # Число итераций пропорционально длине массива - for num in nums - count += 1 - end - - count - end - - # ## Квадратичная сложность ### - def quadratic(n) - count = 0 - - # Число итераций квадратично зависит от размера данных n - for i in 0...n - for j in 0...n - count += 1 - end - end - - count - end - - # ## Квадратичная сложность (пузырьковая сортировка) ### - def bubble_sort(nums) - count = 0 # Счетчик - - # Внешний цикл: неотсортированный диапазон [0, i] - for i in (nums.length - 1).downto(0) - # Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец - for j in 0...i - if nums[j] > nums[j + 1] - # Поменять местами nums[j] и nums[j + 1] - tmp = nums[j] - nums[j] = nums[j + 1] - nums[j + 1] = tmp - count += 3 # Обмен элементов включает 3 элементарные операции - end - end - end - - count - end - - # ## Экспоненциальная сложность (итеративная реализация) ### - def exponential(n) - count, base = 0, 1 - - # На каждом шаге клетка делится надвое, образуя последовательность 1, 2, 4, 8, ..., 2^(n-1) - (0...n).each do - (0...base).each { count += 1 } - base *= 2 - end - - # count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 - count - end - - # ## Экспоненциальная сложность (рекурсивная реализация) ### - def exp_recur(n) - return 1 if n == 1 - exp_recur(n - 1) + exp_recur(n - 1) + 1 - end - - # ## Логарифмическая сложность (итеративная реализация) ### - def logarithmic(n) - count = 0 - - while n > 1 - n /= 2 - count += 1 - end - - count - end - - # ## Логарифмическая сложность (рекурсивная реализация) ### - def log_recur(n) - return 0 unless n > 1 - log_recur(n / 2) + 1 - end - - # ## Линейно-логарифмическая сложность ### + ### Линейно-логарифмическая сложность ### def linear_log_recur(n) return 1 unless n > 1 @@ -3835,125 +3252,7 @@ $$ === "Ruby" ```ruby title="time_complexity.rb" - =begin - File: time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Постоянная сложность ### - def constant(n) - count = 0 - size = 100000 - - (0...size).each { count += 1 } - - count - end - - # ## Линейная сложность ### - def linear(n) - count = 0 - (0...n).each { count += 1 } - count - end - - # ## Линейная сложность (обход массива) ### - def array_traversal(nums) - count = 0 - - # Число итераций пропорционально длине массива - for num in nums - count += 1 - end - - count - end - - # ## Квадратичная сложность ### - def quadratic(n) - count = 0 - - # Число итераций квадратично зависит от размера данных n - for i in 0...n - for j in 0...n - count += 1 - end - end - - count - end - - # ## Квадратичная сложность (пузырьковая сортировка) ### - def bubble_sort(nums) - count = 0 # Счетчик - - # Внешний цикл: неотсортированный диапазон [0, i] - for i in (nums.length - 1).downto(0) - # Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец - for j in 0...i - if nums[j] > nums[j + 1] - # Поменять местами nums[j] и nums[j + 1] - tmp = nums[j] - nums[j] = nums[j + 1] - nums[j + 1] = tmp - count += 3 # Обмен элементов включает 3 элементарные операции - end - end - end - - count - end - - # ## Экспоненциальная сложность (итеративная реализация) ### - def exponential(n) - count, base = 0, 1 - - # На каждом шаге клетка делится надвое, образуя последовательность 1, 2, 4, 8, ..., 2^(n-1) - (0...n).each do - (0...base).each { count += 1 } - base *= 2 - end - - # count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 - count - end - - # ## Экспоненциальная сложность (рекурсивная реализация) ### - def exp_recur(n) - return 1 if n == 1 - exp_recur(n - 1) + exp_recur(n - 1) + 1 - end - - # ## Логарифмическая сложность (итеративная реализация) ### - def logarithmic(n) - count = 0 - - while n > 1 - n /= 2 - count += 1 - end - - count - end - - # ## Логарифмическая сложность (рекурсивная реализация) ### - def log_recur(n) - return 0 unless n > 1 - log_recur(n / 2) + 1 - end - - # ## Линейно-логарифмическая сложность ### - def linear_log_recur(n) - return 1 unless n > 1 - - count = linear_log_recur(n / 2) + linear_log_recur(n / 2) - (0...n).each { count += 1 } - - count - end - - # ## Факториальная сложность (рекурсивная реализация) ### + ### Факториальная сложность (рекурсивная реализация) ### def factorial_recur(n) return 1 if n == 0 @@ -4339,13 +3638,7 @@ $$ === "Ruby" ```ruby title="worst_best_time_complexity.rb" - =begin - File: worst_best_time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Создать массив с элементами: 1, 2, ..., n в случайном порядке ### + ### Создать массив с элементами: 1, 2, ..., n в случайном порядке ### def random_numbers(n) # Создать массив nums =: 1, 2, 3, ..., n nums = Array.new(n) { |i| i + 1 } @@ -4353,21 +3646,7 @@ $$ nums.shuffle! end - =begin - File: worst_best_time_complexity.rb - Created Time: 2024-03-30 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Создать массив с элементами: 1, 2, ..., n в случайном порядке ### - def random_numbers(n) - # Создать массив nums =: 1, 2, 3, ..., n - nums = Array.new(n) { |i| i + 1 } - # Случайно перемешать элементы массива - nums.shuffle! - end - - # ## Найти индекс числа 1 в массиве nums ### + ### Найти индекс числа 1 в массиве nums ### def find_one(nums) for i in 0...nums.length # Когда элемент 1 находится в начале массива, достигается лучшая временная сложность O(1) diff --git a/ru/docs/chapter_divide_and_conquer/binary_search_recur.md b/ru/docs/chapter_divide_and_conquer/binary_search_recur.md index 5c342b4da..93a795660 100644 --- a/ru/docs/chapter_divide_and_conquer/binary_search_recur.md +++ b/ru/docs/chapter_divide_and_conquer/binary_search_recur.md @@ -422,13 +422,7 @@ comments: true === "Ruby" ```ruby title="binary_search_recur.rb" - =begin - File: binary_search_recur.rb - Created Time: 2024-05-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Бинарный поиск: задача f(i, j) ### + ### Бинарный поиск: задача f(i, j) ### def dfs(nums, target, i, j) # Если интервал пуст, целевой элемент отсутствует, вернуть -1 return -1 if i > j @@ -448,33 +442,7 @@ comments: true end end - =begin - File: binary_search_recur.rb - Created Time: 2024-05-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Бинарный поиск: задача f(i, j) ### - def dfs(nums, target, i, j) - # Если интервал пуст, целевой элемент отсутствует, вернуть -1 - return -1 if i > j - - # Вычислить индекс середины m - m = (i + j) / 2 - - if nums[m] < target - # Рекурсивная подзадача f(m+1, j) - return dfs(nums, target, m + 1, j) - elsif nums[m] > target - # Рекурсивная подзадача f(i, m-1) - return dfs(nums, target, i, m - 1) - else - # Целевой элемент найден, вернуть его индекс - return m - end - end - - # ## Бинарный поиск ### + ### Бинарный поиск ### def binary_search(nums, target) n = nums.length # Решить задачу f(0, n-1) diff --git a/ru/docs/chapter_divide_and_conquer/build_binary_tree_problem.md b/ru/docs/chapter_divide_and_conquer/build_binary_tree_problem.md index 5013cfb94..441e80df9 100644 --- a/ru/docs/chapter_divide_and_conquer/build_binary_tree_problem.md +++ b/ru/docs/chapter_divide_and_conquer/build_binary_tree_problem.md @@ -485,16 +485,7 @@ comments: true === "Ruby" ```ruby title="build_tree.rb" - =begin - File: build_tree.rb - Created Time: 2024-05-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Построить двоичное дерево: разделяй и властвуй ### + ### Построить двоичное дерево: разделяй и властвуй ### def dfs(preorder, inorder_map, i, l, r) # Завершить при пустом диапазоне поддерева return if r - l < 0 @@ -512,34 +503,7 @@ comments: true root end - =begin - File: build_tree.rb - Created Time: 2024-05-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Построить двоичное дерево: разделяй и властвуй ### - def dfs(preorder, inorder_map, i, l, r) - # Завершить при пустом диапазоне поддерева - return if r - l < 0 - - # Инициализировать корневой узел - root = TreeNode.new(preorder[i]) - # Найти m, чтобы разделить левое и правое поддеревья - m = inorder_map[preorder[i]] - # Подзадача: построить левое поддерево - root.left = dfs(preorder, inorder_map, i + 1, l, m - 1) - # Подзадача: построить правое поддерево - root.right = dfs(preorder, inorder_map, i + 1 + m - l, m + 1, r) - - # Вернуть корневой узел - root - end - - # ## Построить двоичное дерево ### + ### Построить двоичное дерево ### def build_tree(preorder, inorder) # Инициализировать хеш-таблицу для хранения соответствия элементов inorder их индексам inorder_map = {} diff --git a/ru/docs/chapter_divide_and_conquer/hanota_problem.md b/ru/docs/chapter_divide_and_conquer/hanota_problem.md index be6e79a07..0d21e6b1e 100644 --- a/ru/docs/chapter_divide_and_conquer/hanota_problem.md +++ b/ru/docs/chapter_divide_and_conquer/hanota_problem.md @@ -510,13 +510,7 @@ comments: true === "Ruby" ```ruby title="hanota.rb" - =begin - File: hanota.rb - Created Time: 2024-05-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Переместить один диск ### + ### Переместить один диск ### def move(src, tar) # Снять диск с вершины src pan = src.pop @@ -524,21 +518,7 @@ comments: true tar << pan end - =begin - File: hanota.rb - Created Time: 2024-05-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Переместить один диск ### - def move(src, tar) - # Снять диск с вершины src - pan = src.pop - # Положить диск на вершину tar - tar << pan - end - - # ## Решить задачу Ханойской башни f(i) ### + ### Решить задачу Ханойской башни f(i) ### def dfs(i, src, buf, tar) # Если в src остался только один диск, сразу переместить его в tar if i == 1 @@ -554,37 +534,7 @@ comments: true dfs(i - 1, buf, src, tar) end - =begin - File: hanota.rb - Created Time: 2024-05-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Переместить один диск ### - def move(src, tar) - # Снять диск с вершины src - pan = src.pop - # Положить диск на вершину tar - tar << pan - end - - # ## Решить задачу Ханойской башни f(i) ### - def dfs(i, src, buf, tar) - # Если в src остался только один диск, сразу переместить его в tar - if i == 1 - move(src, tar) - return - end - - # Подзадача f(i-1): переместить верхние i-1 дисков из src в buf с помощью tar - dfs(i - 1, src, tar, buf) - # Подзадача f(1): переместить оставшийся один диск из src в tar - move(src, tar) - # Подзадача f(i-1): переместить верхние i-1 дисков из buf в tar с помощью src - dfs(i - 1, buf, src, tar) - end - - # ## Решить задачу Ханойской башни ### + ### Решить задачу Ханойской башни ### def solve_hanota(_A, _B, _C) n = _A.length # Переместить верхние n дисков из A в C с помощью B diff --git a/ru/docs/chapter_dynamic_programming/dp_problem_features.md b/ru/docs/chapter_dynamic_programming/dp_problem_features.md index 218369171..58d1206cf 100644 --- a/ru/docs/chapter_dynamic_programming/dp_problem_features.md +++ b/ru/docs/chapter_dynamic_programming/dp_problem_features.md @@ -304,13 +304,7 @@ $$ === "Ruby" ```ruby title="min_cost_climbing_stairs_dp.rb" - =begin - File: min_cost_climbing_stairs_dp.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Минимальная стоимость подъема по лестнице: динамическое программирование ### + ### Минимальная стоимость подъема по лестнице: динамическое программирование ### def min_cost_climbing_stairs_dp(cost) n = cost.length - 1 return cost[n] if n == 1 || n == 2 @@ -564,13 +558,7 @@ $$ === "Ruby" ```ruby title="min_cost_climbing_stairs_dp.rb" - =begin - File: min_cost_climbing_stairs_dp.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Минимальная стоимость подъема по лестнице: динамическое программирование ### + ### Минимальная стоимость подъема по лестнице: динамическое программирование ### def min_cost_climbing_stairs_dp(cost) n = cost.length - 1 return cost[n] if n == 1 || n == 2 @@ -935,13 +923,7 @@ $$ === "Ruby" ```ruby title="climbing_stairs_constraint_dp.rb" - =begin - File: climbing_stairs_constraint_dp.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Подъем по лестнице с ограничениями: динамическое программирование ### + ### Подъем по лестнице с ограничениями: динамическое программирование ### def climbing_stairs_constraint_dp(n) return 1 if n == 1 || n == 2 diff --git a/ru/docs/chapter_dynamic_programming/dp_solution_pipeline.md b/ru/docs/chapter_dynamic_programming/dp_solution_pipeline.md index 0ffa94148..6973429f4 100644 --- a/ru/docs/chapter_dynamic_programming/dp_solution_pipeline.md +++ b/ru/docs/chapter_dynamic_programming/dp_solution_pipeline.md @@ -369,13 +369,7 @@ $$ === "Ruby" ```ruby title="min_path_sum.rb" - =begin - File: min_path_sum.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Минимальная сумма пути: полный перебор ### + ### Минимальная сумма пути: полный перебор ### def min_path_sum_dfs(grid, i, j) # Если это верхняя левая ячейка, завершить поиск return grid[i][j] if i == 0 && j == 0 @@ -732,26 +726,7 @@ $$ === "Ruby" ```ruby title="min_path_sum.rb" - =begin - File: min_path_sum.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Минимальная сумма пути: полный перебор ### - def min_path_sum_dfs(grid, i, j) - # Если это верхняя левая ячейка, завершить поиск - return grid[i][j] if i == 0 && j == 0 - # Если индексы строки или столбца выходят за границы, вернуть стоимость +∞ - return Float::INFINITY if i < 0 || j < 0 - # Вычислить минимальную стоимость пути из левого верхнего угла до (i-1, j) и (i, j-1) - up = min_path_sum_dfs(grid, i - 1, j) - left = min_path_sum_dfs(grid, i, j - 1) - # Вернуть минимальную стоимость пути из левого верхнего угла до (i, j) - [left, up].min + grid[i][j] - end - - # ## Минимальная сумма пути: поиск с мемоизацией ### + ### Минимальная сумма пути: поиск с мемоизацией ### def min_path_sum_dfs_mem(grid, mem, i, j) # Если это верхняя левая ячейка, завершить поиск return grid[0][0] if i == 0 && j == 0 @@ -1122,41 +1097,7 @@ $$ === "Ruby" ```ruby title="min_path_sum.rb" - =begin - File: min_path_sum.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Минимальная сумма пути: полный перебор ### - def min_path_sum_dfs(grid, i, j) - # Если это верхняя левая ячейка, завершить поиск - return grid[i][j] if i == 0 && j == 0 - # Если индексы строки или столбца выходят за границы, вернуть стоимость +∞ - return Float::INFINITY if i < 0 || j < 0 - # Вычислить минимальную стоимость пути из левого верхнего угла до (i-1, j) и (i, j-1) - up = min_path_sum_dfs(grid, i - 1, j) - left = min_path_sum_dfs(grid, i, j - 1) - # Вернуть минимальную стоимость пути из левого верхнего угла до (i, j) - [left, up].min + grid[i][j] - end - - # ## Минимальная сумма пути: поиск с мемоизацией ### - def min_path_sum_dfs_mem(grid, mem, i, j) - # Если это верхняя левая ячейка, завершить поиск - return grid[0][0] if i == 0 && j == 0 - # Если индексы строки или столбца выходят за границы, вернуть стоимость +∞ - return Float::INFINITY if i < 0 || j < 0 - # Если запись уже есть, вернуть сразу - return mem[i][j] if mem[i][j] != -1 - # Минимальная стоимость пути для левой и верхней ячеек - up = min_path_sum_dfs_mem(grid, mem, i - 1, j) - left = min_path_sum_dfs_mem(grid, mem, i, j - 1) - # Сохранить и вернуть минимальную стоимость пути из левого верхнего угла до (i, j) - mem[i][j] = [left, up].min + grid[i][j] - end - - # ## Минимальная сумма пути: динамическое программирование ### + ### Минимальная сумма пути: динамическое программирование ### def min_path_sum_dp(grid) n, m = grid.length, grid.first.length # Инициализация таблицы dp @@ -1545,60 +1486,7 @@ $$ === "Ruby" ```ruby title="min_path_sum.rb" - =begin - File: min_path_sum.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Минимальная сумма пути: полный перебор ### - def min_path_sum_dfs(grid, i, j) - # Если это верхняя левая ячейка, завершить поиск - return grid[i][j] if i == 0 && j == 0 - # Если индексы строки или столбца выходят за границы, вернуть стоимость +∞ - return Float::INFINITY if i < 0 || j < 0 - # Вычислить минимальную стоимость пути из левого верхнего угла до (i-1, j) и (i, j-1) - up = min_path_sum_dfs(grid, i - 1, j) - left = min_path_sum_dfs(grid, i, j - 1) - # Вернуть минимальную стоимость пути из левого верхнего угла до (i, j) - [left, up].min + grid[i][j] - end - - # ## Минимальная сумма пути: поиск с мемоизацией ### - def min_path_sum_dfs_mem(grid, mem, i, j) - # Если это верхняя левая ячейка, завершить поиск - return grid[0][0] if i == 0 && j == 0 - # Если индексы строки или столбца выходят за границы, вернуть стоимость +∞ - return Float::INFINITY if i < 0 || j < 0 - # Если запись уже есть, вернуть сразу - return mem[i][j] if mem[i][j] != -1 - # Минимальная стоимость пути для левой и верхней ячеек - up = min_path_sum_dfs_mem(grid, mem, i - 1, j) - left = min_path_sum_dfs_mem(grid, mem, i, j - 1) - # Сохранить и вернуть минимальную стоимость пути из левого верхнего угла до (i, j) - mem[i][j] = [left, up].min + grid[i][j] - end - - # ## Минимальная сумма пути: динамическое программирование ### - def min_path_sum_dp(grid) - n, m = grid.length, grid.first.length - # Инициализация таблицы dp - dp = Array.new(n) { Array.new(m, 0) } - dp[0][0] = grid[0][0] - # Переход состояний: первая строка - (1...m).each { |j| dp[0][j] = dp[0][j - 1] + grid[0][j] } - # Переход состояний: первый столбец - (1...n).each { |i| dp[i][0] = dp[i - 1][0] + grid[i][0] } - # Переход состояний: остальные строки и столбцы - for i in 1...n - for j in 1...m - dp[i][j] = [dp[i][j - 1], dp[i - 1][j]].min + grid[i][j] - end - end - dp[n -1][m -1] - end - - # ## Минимальная сумма пути: динамическое программирование с оптимизацией памяти ### + ### Минимальная сумма пути: динамическое программирование с оптимизацией памяти ### def min_path_sum_dp_comp(grid) n, m = grid.length, grid.first.length # Инициализация таблицы dp diff --git a/ru/docs/chapter_dynamic_programming/edit_distance_problem.md b/ru/docs/chapter_dynamic_programming/edit_distance_problem.md index 3294e19e0..6b6070f40 100644 --- a/ru/docs/chapter_dynamic_programming/edit_distance_problem.md +++ b/ru/docs/chapter_dynamic_programming/edit_distance_problem.md @@ -454,50 +454,7 @@ $$ === "Ruby" ```ruby title="edit_distance.rb" - =begin - File: edit_distance.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Редакционное расстояние: полный перебор ### - def edit_distance_dfs(s, t, i, j) - # Если s и t пусты, вернуть 0 - return 0 if i == 0 && j == 0 - # Если s пусто, вернуть длину t - return j if i == 0 - # Если t пусто, вернуть длину s - return i if j == 0 - # Если два символа равны, сразу пропустить их - return edit_distance_dfs(s, t, i - 1, j - 1) if s[i - 1] == t[j - 1] - # Минимальное число шагов редактирования = минимальное число шагов для вставки, удаления и замены + 1 - insert = edit_distance_dfs(s, t, i, j - 1) - delete = edit_distance_dfs(s, t, i - 1, j) - replace = edit_distance_dfs(s, t, i - 1, j - 1) - # Вернуть минимальное число шагов редактирования - [insert, delete, replace].min + 1 - end - - def edit_distance_dfs_mem(s, t, mem, i, j) - # Если s и t пусты, вернуть 0 - return 0 if i == 0 && j == 0 - # Если s пусто, вернуть длину t - return j if i == 0 - # Если t пусто, вернуть длину s - return i if j == 0 - # Если запись уже есть, сразу вернуть ее - return mem[i][j] if mem[i][j] != -1 - # Если два символа равны, сразу пропустить их - return edit_distance_dfs_mem(s, t, mem, i - 1, j - 1) if s[i - 1] == t[j - 1] - # Минимальное число шагов редактирования = минимальное число шагов для вставки, удаления и замены + 1 - insert = edit_distance_dfs_mem(s, t, mem, i, j - 1) - delete = edit_distance_dfs_mem(s, t, mem, i - 1, j) - replace = edit_distance_dfs_mem(s, t, mem, i - 1, j - 1) - # Сохранить и вернуть минимальное число шагов редактирования - mem[i][j] = [insert, delete, replace].min + 1 - end - - # ## Редакционное расстояние: динамическое программирование ### + ### Редакционное расстояние: динамическое программирование ### def edit_distance_dp(s, t) n, m = s.length, t.length dp = Array.new(n + 1) { Array.new(m + 1, 0) } @@ -981,72 +938,7 @@ $$ === "Ruby" ```ruby title="edit_distance.rb" - =begin - File: edit_distance.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Редакционное расстояние: полный перебор ### - def edit_distance_dfs(s, t, i, j) - # Если s и t пусты, вернуть 0 - return 0 if i == 0 && j == 0 - # Если s пусто, вернуть длину t - return j if i == 0 - # Если t пусто, вернуть длину s - return i if j == 0 - # Если два символа равны, сразу пропустить их - return edit_distance_dfs(s, t, i - 1, j - 1) if s[i - 1] == t[j - 1] - # Минимальное число шагов редактирования = минимальное число шагов для вставки, удаления и замены + 1 - insert = edit_distance_dfs(s, t, i, j - 1) - delete = edit_distance_dfs(s, t, i - 1, j) - replace = edit_distance_dfs(s, t, i - 1, j - 1) - # Вернуть минимальное число шагов редактирования - [insert, delete, replace].min + 1 - end - - def edit_distance_dfs_mem(s, t, mem, i, j) - # Если s и t пусты, вернуть 0 - return 0 if i == 0 && j == 0 - # Если s пусто, вернуть длину t - return j if i == 0 - # Если t пусто, вернуть длину s - return i if j == 0 - # Если запись уже есть, сразу вернуть ее - return mem[i][j] if mem[i][j] != -1 - # Если два символа равны, сразу пропустить их - return edit_distance_dfs_mem(s, t, mem, i - 1, j - 1) if s[i - 1] == t[j - 1] - # Минимальное число шагов редактирования = минимальное число шагов для вставки, удаления и замены + 1 - insert = edit_distance_dfs_mem(s, t, mem, i, j - 1) - delete = edit_distance_dfs_mem(s, t, mem, i - 1, j) - replace = edit_distance_dfs_mem(s, t, mem, i - 1, j - 1) - # Сохранить и вернуть минимальное число шагов редактирования - mem[i][j] = [insert, delete, replace].min + 1 - end - - # ## Редакционное расстояние: динамическое программирование ### - def edit_distance_dp(s, t) - n, m = s.length, t.length - dp = Array.new(n + 1) { Array.new(m + 1, 0) } - # Переход состояний: первая строка и первый столбец - (1...(n + 1)).each { |i| dp[i][0] = i } - (1...(m + 1)).each { |j| dp[0][j] = j } - # Переход состояний: остальные строки и столбцы - for i in 1...(n + 1) - for j in 1...(m +1) - if s[i - 1] == t[j - 1] - # Если два символа равны, сразу пропустить их - dp[i][j] = dp[i - 1][j - 1] - else - # Минимальное число шагов редактирования = минимальное число шагов для вставки, удаления и замены + 1 - dp[i][j] = [dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]].min + 1 - end - end - end - dp[n][m] - end - - # ## Редакционное расстояние: динамическое программирование с оптимизацией памяти ### + ### Редакционное расстояние: динамическое программирование с оптимизацией памяти ### def edit_distance_dp_comp(s, t) n, m = s.length, t.length dp = Array.new(m + 1, 0) diff --git a/ru/docs/chapter_dynamic_programming/intro_to_dynamic_programming.md b/ru/docs/chapter_dynamic_programming/intro_to_dynamic_programming.md index bf5aa0db1..0be32977a 100644 --- a/ru/docs/chapter_dynamic_programming/intro_to_dynamic_programming.md +++ b/ru/docs/chapter_dynamic_programming/intro_to_dynamic_programming.md @@ -395,13 +395,7 @@ comments: true === "Ruby" ```ruby title="climbing_stairs_backtrack.rb" - =begin - File: climbing_stairs_backtrack.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Бэктрекинг ### + ### Бэктрекинг ### def backtrack(choices, state, n, res) # Когда подъем достигает n-й ступени, число вариантов увеличивается на 1 res[0] += 1 if state == n @@ -416,28 +410,7 @@ comments: true # Откат end - =begin - File: climbing_stairs_backtrack.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Бэктрекинг ### - def backtrack(choices, state, n, res) - # Когда подъем достигает n-й ступени, число вариантов увеличивается на 1 - res[0] += 1 if state == n - # Перебор всех вариантов выбора - for choice in choices - # Отсечение: нельзя выходить за n-ю ступень - next if state + choice > n - - # Попытка: сделать выбор и обновить состояние - backtrack(choices, state + choice, n, res) - end - # Откат - end - - # ## Подъем по лестнице: бэктрекинг ### + ### Подъем по лестнице: бэктрекинг ### def climbing_stairs_backtrack(n) choices = [1, 2] # Можно подняться на 1 или 2 ступени state = 0 # Начать подъем с 0-й ступени @@ -708,13 +681,7 @@ $$ === "Ruby" ```ruby title="climbing_stairs_dfs.rb" - =begin - File: climbing_stairs_dfs.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Поиск ### + ### Поиск ### def dfs(i) # dp[1] и dp[2] уже известны, вернуть их return i if i == 1 || i == 2 @@ -722,21 +689,7 @@ $$ dfs(i - 1) + dfs(i - 2) end - =begin - File: climbing_stairs_dfs.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Поиск ### - def dfs(i) - # dp[1] и dp[2] уже известны, вернуть их - return i if i == 1 || i == 2 - # dp[i] = dp[i-1] + dp[i-2] - dfs(i - 1) + dfs(i - 2) - end - - # ## Подъем по лестнице: поиск ### + ### Подъем по лестнице: поиск ### def climbing_stairs_dfs(n) dfs(n) end @@ -1088,13 +1041,7 @@ $$ === "Ruby" ```ruby title="climbing_stairs_dfs_mem.rb" - =begin - File: climbing_stairs_dfs_mem.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Поиск с мемоизацией ### + ### Поиск с мемоизацией ### def dfs(i, mem) # dp[1] и dp[2] уже известны, вернуть их return i if i == 1 || i == 2 @@ -1107,26 +1054,7 @@ $$ mem[i] = count end - =begin - File: climbing_stairs_dfs_mem.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Поиск с мемоизацией ### - def dfs(i, mem) - # dp[1] и dp[2] уже известны, вернуть их - return i if i == 1 || i == 2 - # Если запись dp[i] существует, сразу вернуть ее - return mem[i] if mem[i] != -1 - - # dp[i] = dp[i-1] + dp[i-2] - count = dfs(i - 1, mem) + dfs(i - 2, mem) - # Сохранить dp[i] - mem[i] = count - end - - # ## Подъем по лестнице: поиск с мемоизацией ### + ### Подъем по лестнице: поиск с мемоизацией ### def climbing_stairs_dfs_mem(n) # mem[i] хранит число способов подняться на i-ю ступень, -1 означает отсутствие записи mem = Array.new(n + 1, -1) @@ -1395,13 +1323,7 @@ $$ === "Ruby" ```ruby title="climbing_stairs_dp.rb" - =begin - File: climbing_stairs_dp.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Подъем по лестнице: динамическое программирование ### + ### Подъем по лестнице: динамическое программирование ### def climbing_stairs_dp(n) return n if n == 1 || n == 2 @@ -1642,27 +1564,7 @@ $$ === "Ruby" ```ruby title="climbing_stairs_dp.rb" - =begin - File: climbing_stairs_dp.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Подъем по лестнице: динамическое программирование ### - def climbing_stairs_dp(n) - return n if n == 1 || n == 2 - - # Инициализация таблицы dp для хранения решений подзадач - dp = Array.new(n + 1, 0) - # Начальное состояние: заранее задать решения наименьших подзадач - dp[1], dp[2] = 1, 2 - # Переход состояний: постепенное решение больших подзадач через меньшие - (3...(n + 1)).each { |i| dp[i] = dp[i - 1] + dp[i - 2] } - - dp[n] - end - - # ## Подъем по лестнице: динамическое программирование с оптимизацией памяти ### + ### Подъем по лестнице: динамическое программирование с оптимизацией памяти ### def climbing_stairs_dp_comp(n) return n if n == 1 || n == 2 diff --git a/ru/docs/chapter_dynamic_programming/knapsack_problem.md b/ru/docs/chapter_dynamic_programming/knapsack_problem.md index 426367b6b..191f01d4a 100644 --- a/ru/docs/chapter_dynamic_programming/knapsack_problem.md +++ b/ru/docs/chapter_dynamic_programming/knapsack_problem.md @@ -324,13 +324,7 @@ $$ === "Ruby" ```ruby title="knapsack.rb" - =begin - File: knapsack.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Рюкзак 0-1: полный перебор ### + ### Рюкзак 0-1: полный перебор ### def knapsack_dfs(wgt, val, i, c) # Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0 return 0 if i == 0 || c == 0 @@ -696,26 +690,7 @@ $$ === "Ruby" ```ruby title="knapsack.rb" - =begin - File: knapsack.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Рюкзак 0-1: полный перебор ### - def knapsack_dfs(wgt, val, i, c) - # Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0 - return 0 if i == 0 || c == 0 - # Если вместимость рюкзака превышена, можно только не класть предмет в рюкзак - return knapsack_dfs(wgt, val, i - 1, c) if wgt[i - 1] > c - # Вычислить максимальную стоимость для случаев, когда предмет i не кладут и кладут - no = knapsack_dfs(wgt, val, i - 1, c) - yes = knapsack_dfs(wgt, val, i - 1, c - wgt[i - 1]) + val[i - 1] - # Вернуть вариант с большей стоимостью из двух возможных - [no, yes].max - end - - # ## Рюкзак 0-1: поиск с мемоизацией ### + ### Рюкзак 0-1: поиск с мемоизацией ### def knapsack_dfs_mem(wgt, val, mem, i, c) # Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0 return 0 if i == 0 || c == 0 @@ -1061,41 +1036,7 @@ $$ === "Ruby" ```ruby title="knapsack.rb" - =begin - File: knapsack.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Рюкзак 0-1: полный перебор ### - def knapsack_dfs(wgt, val, i, c) - # Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0 - return 0 if i == 0 || c == 0 - # Если вместимость рюкзака превышена, можно только не класть предмет в рюкзак - return knapsack_dfs(wgt, val, i - 1, c) if wgt[i - 1] > c - # Вычислить максимальную стоимость для случаев, когда предмет i не кладут и кладут - no = knapsack_dfs(wgt, val, i - 1, c) - yes = knapsack_dfs(wgt, val, i - 1, c - wgt[i - 1]) + val[i - 1] - # Вернуть вариант с большей стоимостью из двух возможных - [no, yes].max - end - - # ## Рюкзак 0-1: поиск с мемоизацией ### - def knapsack_dfs_mem(wgt, val, mem, i, c) - # Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0 - return 0 if i == 0 || c == 0 - # Если запись уже есть, вернуть сразу - return mem[i][c] if mem[i][c] != -1 - # Если вместимость рюкзака превышена, можно только не класть предмет в рюкзак - return knapsack_dfs_mem(wgt, val, mem, i - 1, c) if wgt[i - 1] > c - # Вычислить максимальную стоимость для случаев, когда предмет i не кладут и кладут - no = knapsack_dfs_mem(wgt, val, mem, i - 1, c) - yes = knapsack_dfs_mem(wgt, val, mem, i - 1, c - wgt[i - 1]) + val[i - 1] - # Сохранить и вернуть вариант с большей стоимостью из двух решений - mem[i][c] = [no, yes].max - end - - # ## Рюкзак 0-1: динамическое программирование ### + ### Рюкзак 0-1: динамическое программирование ### def knapsack_dp(wgt, val, cap) n = wgt.length # Инициализация таблицы dp @@ -1476,61 +1417,7 @@ $$ === "Ruby" ```ruby title="knapsack.rb" - =begin - File: knapsack.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Рюкзак 0-1: полный перебор ### - def knapsack_dfs(wgt, val, i, c) - # Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0 - return 0 if i == 0 || c == 0 - # Если вместимость рюкзака превышена, можно только не класть предмет в рюкзак - return knapsack_dfs(wgt, val, i - 1, c) if wgt[i - 1] > c - # Вычислить максимальную стоимость для случаев, когда предмет i не кладут и кладут - no = knapsack_dfs(wgt, val, i - 1, c) - yes = knapsack_dfs(wgt, val, i - 1, c - wgt[i - 1]) + val[i - 1] - # Вернуть вариант с большей стоимостью из двух возможных - [no, yes].max - end - - # ## Рюкзак 0-1: поиск с мемоизацией ### - def knapsack_dfs_mem(wgt, val, mem, i, c) - # Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0 - return 0 if i == 0 || c == 0 - # Если запись уже есть, вернуть сразу - return mem[i][c] if mem[i][c] != -1 - # Если вместимость рюкзака превышена, можно только не класть предмет в рюкзак - return knapsack_dfs_mem(wgt, val, mem, i - 1, c) if wgt[i - 1] > c - # Вычислить максимальную стоимость для случаев, когда предмет i не кладут и кладут - no = knapsack_dfs_mem(wgt, val, mem, i - 1, c) - yes = knapsack_dfs_mem(wgt, val, mem, i - 1, c - wgt[i - 1]) + val[i - 1] - # Сохранить и вернуть вариант с большей стоимостью из двух решений - mem[i][c] = [no, yes].max - end - - # ## Рюкзак 0-1: динамическое программирование ### - def knapsack_dp(wgt, val, cap) - n = wgt.length - # Инициализация таблицы dp - dp = Array.new(n + 1) { Array.new(cap + 1, 0) } - # Переход состояний - for i in 1...(n + 1) - for c in 1...(cap + 1) - if wgt[i - 1] > c - # Если вместимость рюкзака превышена, предмет i не выбирать - dp[i][c] = dp[i - 1][c] - else - # Большее из двух решений: не брать или взять предмет i - dp[i][c] = [dp[i - 1][c], dp[i - 1][c - wgt[i - 1]] + val[i - 1]].max - end - end - end - dp[n][cap] - end - - # ## Рюкзак 0-1: динамическое программирование с оптимизацией памяти ### + ### Рюкзак 0-1: динамическое программирование с оптимизацией памяти ### def knapsack_dp_comp(wgt, val, cap) n = wgt.length # Инициализация таблицы dp diff --git a/ru/docs/chapter_dynamic_programming/unbounded_knapsack_problem.md b/ru/docs/chapter_dynamic_programming/unbounded_knapsack_problem.md index 23e7a7da8..b53fe1a4b 100644 --- a/ru/docs/chapter_dynamic_programming/unbounded_knapsack_problem.md +++ b/ru/docs/chapter_dynamic_programming/unbounded_knapsack_problem.md @@ -350,13 +350,7 @@ $$ === "Ruby" ```ruby title="unbounded_knapsack.rb" - =begin - File: unbounded_knapsack.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Полный рюкзак: динамическое программирование ### + ### Полный рюкзак: динамическое программирование ### def unbounded_knapsack_dp(wgt, val, cap) n = wgt.length # Инициализация таблицы dp @@ -709,13 +703,7 @@ $$ === "Ruby" ```ruby title="unbounded_knapsack.rb" - =begin - File: unbounded_knapsack.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Полный рюкзак: динамическое программирование ### + ### Полный рюкзак: динамическое программирование ### def unbounded_knapsack_dp(wgt, val, cap) n = wgt.length # Инициализация таблицы dp @@ -735,7 +723,7 @@ $$ dp[n][cap] end - # ## Полный рюкзак: динамическое программирование с оптимизацией памяти ##3 + ### Полный рюкзак: динамическое программирование с оптимизацией памяти ##3 def unbounded_knapsack_dp_comp(wgt, val, cap) n = wgt.length # Инициализация таблицы dp @@ -1180,13 +1168,7 @@ $$ === "Ruby" ```ruby title="coin_change.rb" - =begin - File: coin_change.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Размен монет: динамическое программирование ### + ### Размен монет: динамическое программирование ### def coin_change_dp(coins, amt) n = coins.length _MAX = amt + 1 @@ -1601,36 +1583,7 @@ $$ === "Ruby" ```ruby title="coin_change.rb" - =begin - File: coin_change.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Размен монет: динамическое программирование ### - def coin_change_dp(coins, amt) - n = coins.length - _MAX = amt + 1 - # Инициализация таблицы dp - dp = Array.new(n + 1) { Array.new(amt + 1, 0) } - # Переход состояний: первая строка и первый столбец - (1...(amt + 1)).each { |a| dp[0][a] = _MAX } - # Переход состояний: остальные строки и столбцы - for i in 1...(n + 1) - for a in 1...(amt + 1) - 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]] + 1].min - end - end - end - dp[n][amt] != _MAX ? dp[n][amt] : -1 - end - - # ## Размен монет: динамическое программирование с оптимизацией памяти ### + ### Размен монет: динамическое программирование с оптимизацией памяти ### def coin_change_dp_comp(coins, amt) n = coins.length _MAX = amt + 1 @@ -2033,13 +1986,7 @@ $$ === "Ruby" ```ruby title="coin_change_ii.rb" - =begin - File: coin_change_ii.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Размен монет II: динамическое программирование ### + ### Размен монет II: динамическое программирование ### def coin_change_ii_dp(coins, amt) n = coins.length # Инициализация таблицы dp @@ -2375,35 +2322,7 @@ $$ === "Ruby" ```ruby title="coin_change_ii.rb" - =begin - File: coin_change_ii.rb - Created Time: 2024-05-29 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Размен монет II: динамическое программирование ### - def coin_change_ii_dp(coins, amt) - n = coins.length - # Инициализация таблицы dp - dp = Array.new(n + 1) { Array.new(amt + 1, 0) } - # Инициализация первого столбца - (0...(n + 1)).each { |i| dp[i][0] = 1 } - # Переход состояний - for i in 1...(n + 1) - for a in 1...(amt + 1) - 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]] - end - end - end - dp[n][amt] - end - - # ## Размен монет II: динамическое программирование с оптимизацией памяти ### + ### Размен монет II: динамическое программирование с оптимизацией памяти ### def coin_change_ii_dp_comp(coins, amt) n = coins.length # Инициализация таблицы dp diff --git a/ru/docs/chapter_graph/graph_operations.md b/ru/docs/chapter_graph/graph_operations.md index f9441c2e7..ffaadaaf7 100644 --- a/ru/docs/chapter_graph/graph_operations.md +++ b/ru/docs/chapter_graph/graph_operations.md @@ -1130,18 +1130,10 @@ comments: true === "Ruby" ```ruby title="graph_adjacency_matrix.rb" - =begin - File: graph_adjacency_matrix.rb - Created Time: 2024-04-25 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Класс неориентированного графа на основе матрицы смежности ### + ### Класс неориентированного графа на основе матрицы смежности ### class GraphAdjMat def initialize(vertices, edges) - # ## Конструктор ### + ### Конструктор ### # Список вершин: элементы представляют «значения вершин», а индексы — «индексы вершин» @vertices = [] # Матрица смежности, где индексы строк и столбцов соответствуют «индексам вершин» @@ -1153,12 +1145,12 @@ comments: true edges.each { |e| add_edge(e[0], e[1]) } end - # ## Получение числа вершин ### + ### Получение числа вершин ### def size @vertices.length end - # ## Добавление вершины ### + ### Добавление вершины ### def add_vertex(val) n = size # Добавить значение новой вершины в список вершин @@ -1170,7 +1162,7 @@ comments: true @adj_mat.each { |row| row << 0 } end - # ## Удаление вершины ### + ### Удаление вершины ### def remove_vertex(index) raise IndexError if index >= size @@ -1182,7 +1174,7 @@ comments: true @adj_mat.each { |row| row.delete_at(index) } end - # ## Добавление ребра ### + ### Добавление ребра ### def add_edge(i, j) # Параметры i и j соответствуют индексам элементов vertices # Обработка выхода индекса за границы и случая равенства @@ -1194,7 +1186,7 @@ comments: true @adj_mat[j][i] = 1 end - # ## Удаление ребра ### + ### Удаление ребра ### def remove_edge(i, j) # Параметры i и j соответствуют индексам элементов vertices # Обработка выхода индекса за границы и случая равенства @@ -1205,7 +1197,7 @@ comments: true @adj_mat[j][i] = 0 end - # ## Вывести матрицу смежности ### + ### Вывести матрицу смежности ### def __print__ puts "Список вершин = #{@vertices}" puts 'Матрица смежности =' @@ -2303,19 +2295,11 @@ comments: true === "Ruby" ```ruby title="graph_adjacency_list.rb" - =begin - File: graph_adjacency_list.rb - Created Time: 2024-04-25 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/vertex' - - # ## Класс неориентированного графа на основе списка смежности ### + ### Класс неориентированного графа на основе списка смежности ### class GraphAdjList attr_reader :adj_list - # ## Конструктор ### + ### Конструктор ### def initialize(edges) # Список смежности, где key — вершина, а value — все смежные ей вершины @adj_list = {} @@ -2327,12 +2311,12 @@ comments: true end end - # ## Получение числа вершин ### + ### Получение числа вершин ### def size @adj_list.length end - # ## Добавление ребра ### + ### Добавление ребра ### def add_edge(vet1, vet2) raise ArgumentError if !@adj_list.include?(vet1) || !@adj_list.include?(vet2) @@ -2340,7 +2324,7 @@ comments: true @adj_list[vet2] << vet1 end - # ## Удаление ребра ### + ### Удаление ребра ### def remove_edge(vet1, vet2) raise ArgumentError if !@adj_list.include?(vet1) || !@adj_list.include?(vet2) @@ -2349,7 +2333,7 @@ comments: true @adj_list[vet2].delete(vet1) end - # ## Добавление вершины ### + ### Добавление вершины ### def add_vertex(vet) return if @adj_list.include?(vet) @@ -2357,7 +2341,7 @@ comments: true @adj_list[vet] = [] end - # ## Удаление вершины ### + ### Удаление вершины ### def remove_vertex(vet) raise ArgumentError unless @adj_list.include?(vet) @@ -2369,7 +2353,7 @@ comments: true end end - # ## Вывести список смежности ### + ### Вывести список смежности ### def __print__ puts 'Список смежности =' for vertex in @adj_list diff --git a/ru/docs/chapter_graph/graph_traversal.md b/ru/docs/chapter_graph/graph_traversal.md index 4448e3ae1..d28a36c8b 100644 --- a/ru/docs/chapter_graph/graph_traversal.md +++ b/ru/docs/chapter_graph/graph_traversal.md @@ -450,17 +450,7 @@ BFS обычно реализуется с помощью очереди, код === "Ruby" ```ruby title="graph_bfs.rb" - =begin - File: graph_bfs.rb - Created Time: 2024-04-25 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require 'set' - require_relative './graph_adjacency_list' - require_relative '../utils/vertex' - - # ## Обход в ширину ### + ### Обход в ширину ### def graph_bfs(graph, start_vet) # Использовать список смежности для представления графа, чтобы получать все смежные вершины заданной вершины # Последовательность обхода вершин @@ -921,17 +911,7 @@ BFS обычно реализуется с помощью очереди, код === "Ruby" ```ruby title="graph_dfs.rb" - =begin - File: graph_dfs.rb - Created Time: 2024-04-25 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require 'set' - require_relative './graph_adjacency_list' - require_relative '../utils/vertex' - - # ## Вспомогательная функция обхода в глубину ### + ### Вспомогательная функция обхода в глубину ### def dfs(graph, visited, res, vet) res << vet # Отметить посещенную вершину visited.add(vet) # Отметить эту вершину как посещенную @@ -943,29 +923,7 @@ BFS обычно реализуется с помощью очереди, код end end - =begin - File: graph_dfs.rb - Created Time: 2024-04-25 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require 'set' - require_relative './graph_adjacency_list' - require_relative '../utils/vertex' - - # ## Вспомогательная функция обхода в глубину ### - def dfs(graph, visited, res, vet) - res << vet # Отметить посещенную вершину - visited.add(vet) # Отметить эту вершину как посещенную - # Обойти все смежные вершины данной вершины - for adj_vet in graph.adj_list[vet] - next if visited.include?(adj_vet) # Пропустить уже посещенную вершину - # Рекурсивно обходить смежные вершины - dfs(graph, visited, res, adj_vet) - end - end - - # ## Обход в глубину ### + ### Обход в глубину ### def graph_dfs(graph, start_vet) # Использовать список смежности для представления графа, чтобы получать все смежные вершины заданной вершины # Последовательность обхода вершин diff --git a/ru/docs/chapter_greedy/fractional_knapsack_problem.md b/ru/docs/chapter_greedy/fractional_knapsack_problem.md index 6e8106fc9..525633d8c 100644 --- a/ru/docs/chapter_greedy/fractional_knapsack_problem.md +++ b/ru/docs/chapter_greedy/fractional_knapsack_problem.md @@ -496,13 +496,7 @@ comments: true === "Ruby" ```ruby title="fractional_knapsack.rb" - =begin - File: fractional_knapsack.rb - Created Time: 2024-05-07 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Предмет ### + ### Предмет ### class Item attr_accessor :w # Вес предмета attr_accessor :v # Стоимость предмета @@ -513,24 +507,7 @@ comments: true end end - =begin - File: fractional_knapsack.rb - Created Time: 2024-05-07 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Предмет ### - class Item - attr_accessor :w # Вес предмета - attr_accessor :v # Стоимость предмета - - def initialize(w, v) - @w = w - @v = v - end - end - - # ## Дробный рюкзак: жадный алгоритм ### + ### Дробный рюкзак: жадный алгоритм ### def fractional_knapsack(wgt, val, cap) # Создать список предметов с двумя свойствами: вес и стоимость items = wgt.each_with_index.map { |w, i| Item.new(w, val[i]) } diff --git a/ru/docs/chapter_greedy/greedy_algorithm.md b/ru/docs/chapter_greedy/greedy_algorithm.md index ae44de064..1e578d50e 100644 --- a/ru/docs/chapter_greedy/greedy_algorithm.md +++ b/ru/docs/chapter_greedy/greedy_algorithm.md @@ -310,13 +310,7 @@ comments: true === "Ruby" ```ruby title="coin_change_greedy.rb" - =begin - File: coin_change_greedy.rb - Created Time: 2024-05-07 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Размен монет: жадный алгоритм ### + ### Размен монет: жадный алгоритм ### def coin_change_greedy(coins, amt) # Предположить, что список coins упорядочен i = coins.length - 1 diff --git a/ru/docs/chapter_greedy/max_capacity_problem.md b/ru/docs/chapter_greedy/max_capacity_problem.md index 51be8b4b9..db27f34e5 100644 --- a/ru/docs/chapter_greedy/max_capacity_problem.md +++ b/ru/docs/chapter_greedy/max_capacity_problem.md @@ -397,13 +397,7 @@ $$ === "Ruby" ```ruby title="max_capacity.rb" - =begin - File: max_capacity.rb - Created Time: 2024-05-07 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Максимальная вместимость: жадный алгоритм ### + ### Максимальная вместимость: жадный алгоритм ### def max_capacity(ht) # Инициализировать i и j так, чтобы они располагались по двум концам массива i, j = 0, ht.length - 1 diff --git a/ru/docs/chapter_greedy/max_product_cutting_problem.md b/ru/docs/chapter_greedy/max_product_cutting_problem.md index a3c647bf3..5c98ad8b8 100644 --- a/ru/docs/chapter_greedy/max_product_cutting_problem.md +++ b/ru/docs/chapter_greedy/max_product_cutting_problem.md @@ -371,13 +371,7 @@ $$ === "Ruby" ```ruby title="max_product_cutting.rb" - =begin - File: max_product_cutting.rb - Created Time: 2024-05-07 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Максимальное произведение разрезания: жадный алгоритм ### + ### Максимальное произведение разрезания: жадный алгоритм ### def max_product_cutting(n) # Когда n <= 3, обязательно нужно выделить одну 1 return 1 * (n - 1) if n <= 3 diff --git a/ru/docs/chapter_hashing/hash_algorithm.md b/ru/docs/chapter_hashing/hash_algorithm.md index c9a3f2374..43d3d5f15 100644 --- a/ru/docs/chapter_hashing/hash_algorithm.md +++ b/ru/docs/chapter_hashing/hash_algorithm.md @@ -601,13 +601,7 @@ index = hash(key) % capacity === "Ruby" ```ruby title="simple_hash.rb" - =begin - File: simple_hash.rb - Created Time: 2024-04-14 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Аддитивное хеширование ### + ### Аддитивное хеширование ### def add_hash(key) hash = 0 modulus = 1_000_000_007 @@ -617,23 +611,7 @@ index = hash(key) % capacity hash % modulus end - =begin - File: simple_hash.rb - Created Time: 2024-04-14 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Аддитивное хеширование ### - def add_hash(key) - hash = 0 - modulus = 1_000_000_007 - - key.each_char { |c| hash += c.ord } - - hash % modulus - end - - # ## Мультипликативное хеширование ### + ### Мультипликативное хеширование ### def mul_hash(key) hash = 0 modulus = 1_000_000_007 @@ -643,33 +621,7 @@ index = hash(key) % capacity hash % modulus end - =begin - File: simple_hash.rb - Created Time: 2024-04-14 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Аддитивное хеширование ### - def add_hash(key) - hash = 0 - modulus = 1_000_000_007 - - key.each_char { |c| hash += c.ord } - - hash % modulus - end - - # ## Мультипликативное хеширование ### - def mul_hash(key) - hash = 0 - modulus = 1_000_000_007 - - key.each_char { |c| hash = 31 * hash + c.ord } - - hash % modulus - end - - # ## XOR-хеширование ### + ### XOR-хеширование ### def xor_hash(key) hash = 0 modulus = 1_000_000_007 @@ -679,43 +631,7 @@ index = hash(key) % capacity hash % modulus end - =begin - File: simple_hash.rb - Created Time: 2024-04-14 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Аддитивное хеширование ### - def add_hash(key) - hash = 0 - modulus = 1_000_000_007 - - key.each_char { |c| hash += c.ord } - - hash % modulus - end - - # ## Мультипликативное хеширование ### - def mul_hash(key) - hash = 0 - modulus = 1_000_000_007 - - key.each_char { |c| hash = 31 * hash + c.ord } - - hash % modulus - end - - # ## XOR-хеширование ### - def xor_hash(key) - hash = 0 - modulus = 1_000_000_007 - - key.each_char { |c| hash ^= c.ord } - - hash % modulus - end - - # ## Хеширование с циклическим сдвигом ### + ### Хеширование с циклическим сдвигом ### def rot_hash(key) hash = 0 modulus = 1_000_000_007 diff --git a/ru/docs/chapter_hashing/hash_collision.md b/ru/docs/chapter_hashing/hash_collision.md index 5a0078db7..3dd11d349 100644 --- a/ru/docs/chapter_hashing/hash_collision.md +++ b/ru/docs/chapter_hashing/hash_collision.md @@ -1422,17 +1422,9 @@ comments: true === "Ruby" ```ruby title="hash_map_chaining.rb" - =begin - File: hash_map_chaining.rb - Created Time: 2024-04-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative './array_hash_map' - - # ## Хеш-таблица с цепочками ### + ### Хеш-таблица с цепочками ### class HashMapChaining - # ## Конструктор ### + ### Конструктор ### def initialize @size = 0 # Число пар ключ-значение @capacity = 4 # Вместимость хеш-таблицы @@ -1441,17 +1433,17 @@ comments: true @buckets = Array.new(@capacity) { [] } # Массив корзин end - # ## Хеш-функция ### + ### Хеш-функция ### def hash_func(key) key % @capacity end - # ## Коэффициент загрузки ### + ### Коэффициент загрузки ### def load_factor @size / @capacity end - # ## Операция поиска ### + ### Операция поиска ### def get(key) index = hash_func(key) bucket = @buckets[index] @@ -1463,7 +1455,7 @@ comments: true nil end - # ## Операция добавления ### + ### Операция добавления ### def put(key, val) # Когда коэффициент загрузки превышает порог, выполнить расширение extend if load_factor > @load_thres @@ -1482,7 +1474,7 @@ comments: true @size += 1 end - # ## Операция удаления ### + ### Операция удаления ### def remove(key) index = hash_func(key) bucket = @buckets[index] @@ -1496,7 +1488,7 @@ comments: true end end - # ## Расширение хеш-таблицы ### + ### Расширение хеш-таблицы ### def extend # Временно сохранить исходную хеш-таблицу buckets = @buckets @@ -1512,7 +1504,7 @@ comments: true end end - # ## Вывести хеш-таблицу ### + ### Вывести хеш-таблицу ### def print for bucket in @buckets res = [] @@ -3176,19 +3168,11 @@ comments: true === "Ruby" ```ruby title="hash_map_open_addressing.rb" - =begin - File: hash_map_open_addressing.rb - Created Time: 2024-04-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative './array_hash_map' - - # ## Хеш-таблица с открытой адресацией ### + ### Хеш-таблица с открытой адресацией ### class HashMapOpenAddressing TOMBSTONE = Pair.new(-1, '-1') # Удалить метку - # ## Конструктор ### + ### Конструктор ### def initialize @size = 0 # Число пар ключ-значение @capacity = 4 # Вместимость хеш-таблицы @@ -3197,17 +3181,17 @@ comments: true @buckets = Array.new(@capacity) # Массив корзин end - # ## Хеш-функция ### + ### Хеш-функция ### def hash_func(key) key % @capacity end - # ## Коэффициент загрузки ### + ### Коэффициент загрузки ### def load_factor @size / @capacity end - # ## Найти индекс корзины, соответствующий key ### + ### Найти индекс корзины, соответствующий key ### def find_bucket(key) index = hash_func(key) first_tombstone = -1 @@ -3232,7 +3216,7 @@ comments: true first_tombstone == -1 ? index : first_tombstone end - # ## Операция поиска ### + ### Операция поиска ### def get(key) # Найти индекс корзины, соответствующий key index = find_bucket(key) @@ -3242,7 +3226,7 @@ comments: true nil end - # ## Операция добавления ### + ### Операция добавления ### def put(key, val) # Когда коэффициент загрузки превышает порог, выполнить расширение extend if load_factor > @load_thres @@ -3258,7 +3242,7 @@ comments: true @size += 1 end - # ## Операция удаления ### + ### Операция удаления ### def remove(key) # Найти индекс корзины, соответствующий key index = find_bucket(key) @@ -3269,7 +3253,7 @@ comments: true end end - # ## Расширение хеш-таблицы ### + ### Расширение хеш-таблицы ### def extend # Временно сохранить исходную хеш-таблицу buckets_tmp = @buckets @@ -3283,7 +3267,7 @@ comments: true end end - # ## Вывести хеш-таблицу ### + ### Вывести хеш-таблицу ### def print for pair in @buckets if pair.nil? diff --git a/ru/docs/chapter_hashing/hash_map.md b/ru/docs/chapter_hashing/hash_map.md index ddbb0bae1..3b71915f1 100644 --- a/ru/docs/chapter_hashing/hash_map.md +++ b/ru/docs/chapter_hashing/hash_map.md @@ -1677,13 +1677,7 @@ index = hash(key) % capacity === "Ruby" ```ruby title="array_hash_map.rb" - =begin - File: array_hash_map.rb - Created Time: 2024-04-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Пара ключ-значение ### + ### Пара ключ-значение ### class Pair attr_accessor :key, :val @@ -1693,36 +1687,20 @@ index = hash(key) % capacity end end - =begin - File: array_hash_map.rb - Created Time: 2024-04-13 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Пара ключ-значение ### - class Pair - attr_accessor :key, :val - - def initialize(key, val) - @key = key - @val = val - end - end - - # ## Хеш-таблица на основе массива ### + ### Хеш-таблица на основе массива ### class ArrayHashMap - # ## Конструктор ### + ### Конструктор ### def initialize # Инициализировать массив, содержащий 100 корзин @buckets = Array.new(100) end - # ## Хеш-функция ### + ### Хеш-функция ### def hash_func(key) index = key % 100 end - # ## Операция поиска ### + ### Операция поиска ### def get(key) index = hash_func(key) pair = @buckets[index] @@ -1731,42 +1709,42 @@ index = hash(key) % capacity pair.val end - # ## Операция добавления ### + ### Операция добавления ### def put(key, val) pair = Pair.new(key, val) index = hash_func(key) @buckets[index] = pair end - # ## Операция удаления ### + ### Операция удаления ### def remove(key) index = hash_func(key) # Присвоить nil, что означает удаление @buckets[index] = nil end - # ## Получить все пары ключ-значение ### + ### Получить все пары ключ-значение ### def entry_set result = [] @buckets.each { |pair| result << pair unless pair.nil? } result end - # ## Получить все ключи ### + ### Получить все ключи ### def key_set result = [] @buckets.each { |pair| result << pair.key unless pair.nil? } result end - # ## Получить все значения ### + ### Получить все значения ### def value_set result = [] @buckets.each { |pair| result << pair.val unless pair.nil? } result end - # ## Вывести хеш-таблицу ### + ### Вывести хеш-таблицу ### def print @buckets.each { |pair| puts "#{pair.key} -> #{pair.val}" unless pair.nil? } end diff --git a/ru/docs/chapter_heap/build_heap.md b/ru/docs/chapter_heap/build_heap.md index ac5a888bf..6213b4886 100644 --- a/ru/docs/chapter_heap/build_heap.md +++ b/ru/docs/chapter_heap/build_heap.md @@ -311,19 +311,7 @@ comments: true === "Ruby" ```ruby title="my_heap.rb" - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### + ### Конструктор, строящий кучу по входному списку ### def initialize(nums) # Добавить элементы списка в кучу без изменений @max_heap = nums diff --git a/ru/docs/chapter_heap/heap.md b/ru/docs/chapter_heap/heap.md index f3578fab1..6d6ccd66a 100644 --- a/ru/docs/chapter_heap/heap.md +++ b/ru/docs/chapter_heap/heap.md @@ -669,98 +669,17 @@ comments: true === "Ruby" ```ruby title="my_heap.rb" - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### - def initialize(nums) - # Добавить элементы списка в кучу без изменений - @max_heap = nums - # Выполнить heapify для всех узлов, кроме листовых - parent(size - 1).downto(0) do |i| - sift_down(i) - end - end - - # ## Получить индекс левого дочернего узла ### + ### Получить индекс левого дочернего узла ### def left(i) 2 * i + 1 end - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### - def initialize(nums) - # Добавить элементы списка в кучу без изменений - @max_heap = nums - # Выполнить heapify для всех узлов, кроме листовых - parent(size - 1).downto(0) do |i| - sift_down(i) - end - end - - # ## Получить индекс левого дочернего узла ### - def left(i) - 2 * i + 1 - end - - # ## Получить индекс правого дочернего узла ### + ### Получить индекс правого дочернего узла ### def right(i) 2 * i + 2 end - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### - def initialize(nums) - # Добавить элементы списка в кучу без изменений - @max_heap = nums - # Выполнить heapify для всех узлов, кроме листовых - parent(size - 1).downto(0) do |i| - sift_down(i) - end - end - - # ## Получить индекс левого дочернего узла ### - def left(i) - 2 * i + 1 - end - - # ## Получить индекс правого дочернего узла ### - def right(i) - 2 * i + 2 - end - - # ## Получить индекс родительского узла ### + ### Получить индекс родительского узла ### def parent(i) (i - 1) / 2 # Округление вниз при делении end @@ -880,59 +799,7 @@ comments: true === "Ruby" ```ruby title="my_heap.rb" - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### - def initialize(nums) - # Добавить элементы списка в кучу без изменений - @max_heap = nums - # Выполнить heapify для всех узлов, кроме листовых - parent(size - 1).downto(0) do |i| - sift_down(i) - end - end - - # ## Получить индекс левого дочернего узла ### - def left(i) - 2 * i + 1 - end - - # ## Получить индекс правого дочернего узла ### - def right(i) - 2 * i + 2 - end - - # ## Получить индекс родительского узла ### - def parent(i) - (i - 1) / 2 # Округление вниз при делении - end - - # ## Обмен элементов ### - def swap(i, j) - @max_heap[i], @max_heap[j] = @max_heap[j], @max_heap[i] - end - - # ## Получить размер кучи ### - def size - @max_heap.length - end - - # ## Проверка, пуста ли куча ### - def is_empty? - size == 0 - end - - # ## Доступ к элементу на вершине кучи ### + ### Доступ к элементу на вершине кучи ### def peek @max_heap[0] end @@ -1320,64 +1187,7 @@ comments: true === "Ruby" ```ruby title="my_heap.rb" - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### - def initialize(nums) - # Добавить элементы списка в кучу без изменений - @max_heap = nums - # Выполнить heapify для всех узлов, кроме листовых - parent(size - 1).downto(0) do |i| - sift_down(i) - end - end - - # ## Получить индекс левого дочернего узла ### - def left(i) - 2 * i + 1 - end - - # ## Получить индекс правого дочернего узла ### - def right(i) - 2 * i + 2 - end - - # ## Получить индекс родительского узла ### - def parent(i) - (i - 1) / 2 # Округление вниз при делении - end - - # ## Обмен элементов ### - def swap(i, j) - @max_heap[i], @max_heap[j] = @max_heap[j], @max_heap[i] - end - - # ## Получить размер кучи ### - def size - @max_heap.length - end - - # ## Проверка, пуста ли куча ### - def is_empty? - size == 0 - end - - # ## Доступ к элементу на вершине кучи ### - def peek - @max_heap[0] - end - - # ## Добавление элемента в кучу ### + ### Добавление элемента в кучу ### def push(val) # Добавление узла @max_heap << val @@ -1385,72 +1195,7 @@ comments: true sift_up(size - 1) end - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### - def initialize(nums) - # Добавить элементы списка в кучу без изменений - @max_heap = nums - # Выполнить heapify для всех узлов, кроме листовых - parent(size - 1).downto(0) do |i| - sift_down(i) - end - end - - # ## Получить индекс левого дочернего узла ### - def left(i) - 2 * i + 1 - end - - # ## Получить индекс правого дочернего узла ### - def right(i) - 2 * i + 2 - end - - # ## Получить индекс родительского узла ### - def parent(i) - (i - 1) / 2 # Округление вниз при делении - end - - # ## Обмен элементов ### - def swap(i, j) - @max_heap[i], @max_heap[j] = @max_heap[j], @max_heap[i] - end - - # ## Получить размер кучи ### - def size - @max_heap.length - end - - # ## Проверка, пуста ли куча ### - def is_empty? - size == 0 - end - - # ## Доступ к элементу на вершине кучи ### - def peek - @max_heap[0] - end - - # ## Добавление элемента в кучу ### - def push(val) - # Добавление узла - @max_heap << val - # Просеивание снизу вверх - sift_up(size - 1) - end - - # ## Начиная с узла i, выполнить просеивание снизу вверх ### + ### Начиная с узла i, выполнить просеивание снизу вверх ### def sift_up(i) loop do # Получение родительского узла для узла i @@ -1989,86 +1734,7 @@ comments: true === "Ruby" ```ruby title="my_heap.rb" - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### - def initialize(nums) - # Добавить элементы списка в кучу без изменений - @max_heap = nums - # Выполнить heapify для всех узлов, кроме листовых - parent(size - 1).downto(0) do |i| - sift_down(i) - end - end - - # ## Получить индекс левого дочернего узла ### - def left(i) - 2 * i + 1 - end - - # ## Получить индекс правого дочернего узла ### - def right(i) - 2 * i + 2 - end - - # ## Получить индекс родительского узла ### - def parent(i) - (i - 1) / 2 # Округление вниз при делении - end - - # ## Обмен элементов ### - def swap(i, j) - @max_heap[i], @max_heap[j] = @max_heap[j], @max_heap[i] - end - - # ## Получить размер кучи ### - def size - @max_heap.length - end - - # ## Проверка, пуста ли куча ### - def is_empty? - size == 0 - end - - # ## Доступ к элементу на вершине кучи ### - def peek - @max_heap[0] - end - - # ## Добавление элемента в кучу ### - def push(val) - # Добавление узла - @max_heap << val - # Просеивание снизу вверх - sift_up(size - 1) - end - - # ## Начиная с узла i, выполнить просеивание снизу вверх ### - def sift_up(i) - loop do - # Получение родительского узла для узла i - p = parent(i) - # Завершить heapify, когда «корневой узел уже пройден» или «узел не требует исправления» - break if p < 0 || @max_heap[i] <= @max_heap[p] - # Поменять два узла местами - swap(i, p) - # Циклическое просеивание вверх - i = p - end - end - - # ## Извлечение элемента из кучи ### + ### Извлечение элемента из кучи ### def pop # Обработка пустого случая raise IndexError, "куча пуста" if is_empty? @@ -2082,100 +1748,7 @@ comments: true val end - =begin - File: my_heap.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative '../utils/print_util' - - # ## Максимальная куча ### - class MaxHeap - attr_reader :max_heap - - # ## Конструктор, строящий кучу по входному списку ### - def initialize(nums) - # Добавить элементы списка в кучу без изменений - @max_heap = nums - # Выполнить heapify для всех узлов, кроме листовых - parent(size - 1).downto(0) do |i| - sift_down(i) - end - end - - # ## Получить индекс левого дочернего узла ### - def left(i) - 2 * i + 1 - end - - # ## Получить индекс правого дочернего узла ### - def right(i) - 2 * i + 2 - end - - # ## Получить индекс родительского узла ### - def parent(i) - (i - 1) / 2 # Округление вниз при делении - end - - # ## Обмен элементов ### - def swap(i, j) - @max_heap[i], @max_heap[j] = @max_heap[j], @max_heap[i] - end - - # ## Получить размер кучи ### - def size - @max_heap.length - end - - # ## Проверка, пуста ли куча ### - def is_empty? - size == 0 - end - - # ## Доступ к элементу на вершине кучи ### - def peek - @max_heap[0] - end - - # ## Добавление элемента в кучу ### - def push(val) - # Добавление узла - @max_heap << val - # Просеивание снизу вверх - sift_up(size - 1) - end - - # ## Начиная с узла i, выполнить просеивание снизу вверх ### - def sift_up(i) - loop do - # Получение родительского узла для узла i - p = parent(i) - # Завершить heapify, когда «корневой узел уже пройден» или «узел не требует исправления» - break if p < 0 || @max_heap[i] <= @max_heap[p] - # Поменять два узла местами - swap(i, p) - # Циклическое просеивание вверх - i = p - end - end - - # ## Извлечение элемента из кучи ### - def pop - # Обработка пустого случая - raise IndexError, "куча пуста" if is_empty? - # Поменять корневой узел с самым правым листом местами (поменять первый и последний элементы) - swap(0, size - 1) - # Удаление узла - val = @max_heap.pop - # Просеивание сверху вниз - sift_down(0) - # Вернуть элемент с вершины кучи - val - end - - # ## Начиная с узла i, выполнить просеивание сверху вниз ### + ### Начиная с узла i, выполнить просеивание сверху вниз ### def sift_down(i) loop do # Определить узел с максимальным значением среди i, l и r и обозначить его как ma diff --git a/ru/docs/chapter_heap/top_k.md b/ru/docs/chapter_heap/top_k.md index 99bbc12e4..c25073323 100644 --- a/ru/docs/chapter_heap/top_k.md +++ b/ru/docs/chapter_heap/top_k.md @@ -437,39 +437,7 @@ comments: true === "Ruby" ```ruby title="top_k.rb" - =begin - File: top_k.rb - Created Time: 2024-04-19 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative "./my_heap" - - # ## Добавление элемента в кучу ### - def push_min_heap(heap, val) - # Инвертировать знак элемента - heap.push(-val) - end - - # ## Извлечение элемента из кучи ### - def pop_min_heap(heap) - # Инвертировать знак элемента - -heap.pop - end - - # ## Доступ к элементу на вершине кучи ### - def peek_min_heap(heap) - # Инвертировать знак элемента - -heap.peek - end - - # ## Извлечение элементов из кучи ### - def get_min_heap(heap) - # Инвертировать все элементы кучи - heap.max_heap.map { |x| -x } - end - - # ## Поиск k наибольших элементов массива с помощью кучи ### + ### Поиск k наибольших элементов массива с помощью кучи ### def top_k_heap(nums, k) # Инициализация минимальной кучи # Обратите внимание: мы инвертируем все элементы кучи, чтобы с помощью максимальной кучи имитировать минимальную diff --git a/ru/docs/chapter_searching/binary_search.md b/ru/docs/chapter_searching/binary_search.md index 2e22fbe2f..0fa403275 100644 --- a/ru/docs/chapter_searching/binary_search.md +++ b/ru/docs/chapter_searching/binary_search.md @@ -339,13 +339,7 @@ comments: true === "Ruby" ```ruby title="binary_search.rb" - =begin - File: binary_search.rb - Created Time: 2024-04-09 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - # ## Бинарный поиск (двусторонне замкнутый интервал) ### + ### Бинарный поиск (двусторонне замкнутый интервал) ### def binary_search(nums, target) # Инициализировать двусторонне замкнутый интервал [0, n-1], то есть i и j указывают на первый и последний элементы массива соответственно i, j = 0, nums.length - 1 @@ -669,35 +663,7 @@ comments: true === "Ruby" ```ruby title="binary_search.rb" - =begin - File: binary_search.rb - Created Time: 2024-04-09 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - # ## Бинарный поиск (двусторонне замкнутый интервал) ### - def binary_search(nums, target) - # Инициализировать двусторонне замкнутый интервал [0, n-1], то есть i и j указывают на первый и последний элементы массива соответственно - i, j = 0, nums.length - 1 - - # Цикл завершается, когда диапазон поиска пуст (при i > j диапазон пуст) - while i <= j - # Теоретически числа в Ruby могут быть сколь угодно большими (ограничены только объемом памяти), поэтому не нужно учитывать переполнение больших чисел - m = (i + j) / 2 # Вычислить индекс середины m - - if nums[m] < target - i = m + 1 # Это означает, что target находится в интервале [m+1, j] - elsif nums[m] > target - j = m - 1 # Это означает, что target находится в интервале [i, m-1] - else - return m # Целевой элемент найден, вернуть его индекс - end - end - - -1 # Целевой элемент не найден, вернуть -1 - end - - # ## Бинарный поиск (лево замкнутый, право открытый интервал) ### + ### Бинарный поиск (лево замкнутый, право открытый интервал) ### def binary_search_lcro(nums, target) # Инициализировать лево замкнутый, право открытый интервал [0, n), то есть i и j указывают на первый элемент массива и позицию сразу за последним элементом соответственно i, j = 0, nums.length diff --git a/ru/docs/chapter_searching/binary_search_edge.md b/ru/docs/chapter_searching/binary_search_edge.md index 4ca657b10..e7cd5c01a 100644 --- a/ru/docs/chapter_searching/binary_search_edge.md +++ b/ru/docs/chapter_searching/binary_search_edge.md @@ -212,15 +212,7 @@ comments: true === "Ruby" ```ruby title="binary_search_edge.rb" - =begin - File: binary_search_edge.rb - Created Time: 2024-04-09 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative './binary_search_insertion' - - # ## Бинарный поиск самого левого target ### + ### Бинарный поиск самого левого target ### def binary_search_left_edge(nums, target) # Эквивалентно поиску точки вставки target i = binary_search_insertion(nums, target) @@ -472,26 +464,7 @@ comments: true === "Ruby" ```ruby title="binary_search_edge.rb" - =begin - File: binary_search_edge.rb - Created Time: 2024-04-09 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - require_relative './binary_search_insertion' - - # ## Бинарный поиск самого левого target ### - def binary_search_left_edge(nums, target) - # Эквивалентно поиску точки вставки target - i = binary_search_insertion(nums, target) - - # target не найден, вернуть -1 - return -1 if i == nums.length || nums[i] != target - - i # Найти target и вернуть индекс i - end - - # ## Бинарный поиск самого правого target ### + ### Бинарный поиск самого правого target ### def binary_search_right_edge(nums, target) # Преобразовать задачу в поиск самого левого target + 1 i = binary_search_insertion(nums, target + 1) diff --git a/ru/docs/chapter_searching/binary_search_insertion.md b/ru/docs/chapter_searching/binary_search_insertion.md index 5b3e9db08..c1e5fad85 100644 --- a/ru/docs/chapter_searching/binary_search_insertion.md +++ b/ru/docs/chapter_searching/binary_search_insertion.md @@ -293,13 +293,7 @@ comments: true === "Ruby" ```ruby title="binary_search_insertion.rb" - =begin - File: binary_search_insertion.rb - Created Time: 2024-04-09 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - # ## Бинарный поиск точки вставки (без повторяющихся элементов) ### + ### Бинарный поиск точки вставки (без повторяющихся элементов) ### def binary_search_insertion_simple(nums, target) # Инициализировать двусторонне замкнутый интервал [0, n-1] i, j = 0, nums.length - 1 @@ -644,34 +638,7 @@ comments: true === "Ruby" ```ruby title="binary_search_insertion.rb" - =begin - File: binary_search_insertion.rb - Created Time: 2024-04-09 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - # ## Бинарный поиск точки вставки (без повторяющихся элементов) ### - def binary_search_insertion_simple(nums, target) - # Инициализировать двусторонне замкнутый интервал [0, n-1] - i, j = 0, nums.length - 1 - - while i <= j - # Вычислить индекс середины m - m = (i + j) / 2 - - if nums[m] < target - i = m + 1 # target находится в интервале [m+1, j] - elsif nums[m] > target - j = m - 1 # target находится в интервале [i, m-1] - else - return m # Найти target и вернуть точку вставки m - end - end - - i # target не найден, вернуть точку вставки i - end - - # ## Бинарный поиск точки вставки (с повторяющимися элементами) ### + ### Бинарный поиск точки вставки (с повторяющимися элементами) ### def binary_search_insertion(nums, target) # Инициализировать двусторонне замкнутый интервал [0, n-1] i, j = 0, nums.length - 1 diff --git a/ru/docs/chapter_searching/replace_linear_by_hashing.md b/ru/docs/chapter_searching/replace_linear_by_hashing.md index 4826007b3..a52ce9f7c 100644 --- a/ru/docs/chapter_searching/replace_linear_by_hashing.md +++ b/ru/docs/chapter_searching/replace_linear_by_hashing.md @@ -228,13 +228,7 @@ comments: true === "Ruby" ```ruby title="two_sum.rb" - =begin - File: two_sum.rb - Created Time: 2024-04-09 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - # ## Метод 1: полный перебор ### + ### Метод 1: полный перебор ### def two_sum_brute_force(nums, target) # Два вложенных цикла, временная сложность O(n^2) for i in 0...(nums.length - 1) @@ -527,25 +521,7 @@ comments: true === "Ruby" ```ruby title="two_sum.rb" - =begin - File: two_sum.rb - Created Time: 2024-04-09 - Author: Blue Bean (lonnnnnnner@gmail.com) - =end - - # ## Метод 1: полный перебор ### - def two_sum_brute_force(nums, target) - # Два вложенных цикла, временная сложность O(n^2) - for i in 0...(nums.length - 1) - for j in (i + 1)...nums.length - return [i, j] if nums[i] + nums[j] == target - end - end - - [] - end - - # ## Метод 2: вспомогательная хеш-таблица ### + ### Метод 2: вспомогательная хеш-таблица ### def two_sum_hash_table(nums, target) # Вспомогательная хеш-таблица, пространственная сложность O(n) dic = {} diff --git a/ru/docs/chapter_sorting/bubble_sort.md b/ru/docs/chapter_sorting/bubble_sort.md index 8336f7a30..b594b129d 100644 --- a/ru/docs/chapter_sorting/bubble_sort.md +++ b/ru/docs/chapter_sorting/bubble_sort.md @@ -274,13 +274,7 @@ comments: true === "Ruby" ```ruby title="bubble_sort.rb" - =begin - File: bubble_sort.rb - Created Time: 2024-05-02 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Пузырьковая сортировка ### + ### Пузырьковая сортировка ### def bubble_sort(nums) n = nums.length # Внешний цикл: неотсортированный диапазон [0, i] @@ -580,28 +574,7 @@ comments: true === "Ruby" ```ruby title="bubble_sort.rb" - =begin - File: bubble_sort.rb - Created Time: 2024-05-02 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Пузырьковая сортировка ### - def bubble_sort(nums) - n = nums.length - # Внешний цикл: неотсортированный диапазон [0, i] - for i in (n - 1).downto(1) - # Внутренний цикл: переместить максимальный элемент неотсортированного диапазона [0, i] в его правый конец - for j in 0...i - if nums[j] > nums[j + 1] - # Поменять местами nums[j] и nums[j + 1] - nums[j], nums[j + 1] = nums[j + 1], nums[j] - end - end - end - end - - # ## Пузырьковая сортировка (оптимизация флагом) ### + ### Пузырьковая сортировка (оптимизация флагом) ### def bubble_sort_with_flag(nums) n = nums.length # Внешний цикл: неотсортированный диапазон [0, i] diff --git a/ru/docs/chapter_sorting/bucket_sort.md b/ru/docs/chapter_sorting/bucket_sort.md index 60c72cfa3..b19b15615 100644 --- a/ru/docs/chapter_sorting/bucket_sort.md +++ b/ru/docs/chapter_sorting/bucket_sort.md @@ -406,13 +406,7 @@ comments: true === "Ruby" ```ruby title="bucket_sort.rb" - =begin - File: bucket_sort.rb - Created Time: 2024-04-17 - Author: Martin Xu (martin.xus@gmail.com) - =end - - # ## Сортировка корзинами ### + ### Сортировка корзинами ### def bucket_sort(nums) # Инициализировать k = n/2 корзин, предполагая распределение 2 элементов в каждую корзину k = nums.length / 2 diff --git a/ru/docs/chapter_sorting/counting_sort.md b/ru/docs/chapter_sorting/counting_sort.md index 111351ea6..1b99321c0 100644 --- a/ru/docs/chapter_sorting/counting_sort.md +++ b/ru/docs/chapter_sorting/counting_sort.md @@ -340,13 +340,7 @@ comments: true === "Ruby" ```ruby title="counting_sort.rb" - =begin - File: counting_sort.rb - Created Time: 2024-05-02 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Сортировка подсчетом ### + ### Сортировка подсчетом ### def counting_sort_naive(nums) # Простая реализация, не подходит для сортировки объектов # 1. Найти максимальный элемент массива m @@ -857,33 +851,7 @@ $$ === "Ruby" ```ruby title="counting_sort.rb" - =begin - File: counting_sort.rb - Created Time: 2024-05-02 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Сортировка подсчетом ### - def counting_sort_naive(nums) - # Простая реализация, не подходит для сортировки объектов - # 1. Найти максимальный элемент массива m - m = 0 - nums.each { |num| m = [m, num].max } - # 2. Подсчитать число появлений каждой цифры - # counter[num] обозначает число появлений num - counter = Array.new(m + 1, 0) - nums.each { |num| counter[num] += 1 } - # 3. Обойти counter и заполнить исходный массив nums элементами - i = 0 - for num in 0...(m + 1) - (0...counter[num]).each do - nums[i] = num - i += 1 - end - end - end - - # ## Сортировка подсчетом ### + ### Сортировка подсчетом ### def counting_sort(nums) # Полная реализация, позволяет сортировать объекты и является стабильной сортировкой # 1. Найти максимальный элемент массива m diff --git a/ru/docs/chapter_sorting/heap_sort.md b/ru/docs/chapter_sorting/heap_sort.md index a63e766ea..1f2d360a9 100644 --- a/ru/docs/chapter_sorting/heap_sort.md +++ b/ru/docs/chapter_sorting/heap_sort.md @@ -578,13 +578,7 @@ comments: true === "Ruby" ```ruby title="heap_sort.rb" - =begin - File: heap_sort.rb - Created Time: 2024-04-10 - Author: junminhong (junminhong1110@gmail.com) - =end - - # ## Длина кучи равна n; начиная с узла i, выполнить просеивание сверху вниз ### + ### Длина кучи равна n; начиная с узла i, выполнить просеивание сверху вниз ### def sift_down(nums, n, i) while true # Определить узел с максимальным значением среди i, l и r и обозначить его как ma @@ -602,31 +596,7 @@ comments: true end end - =begin - File: heap_sort.rb - Created Time: 2024-04-10 - Author: junminhong (junminhong1110@gmail.com) - =end - - # ## Длина кучи равна n; начиная с узла i, выполнить просеивание сверху вниз ### - def sift_down(nums, n, i) - while true - # Определить узел с максимальным значением среди i, l и r и обозначить его как ma - l = 2 * i + 1 - r = 2 * i + 2 - ma = i - ma = l if l < n && nums[l] > nums[ma] - ma = r if r < n && nums[r] > nums[ma] - # Если узел i уже максимален или индексы l и r вне границ, дальнейшее просеивание не требуется, выйти - break if ma == i - # Поменять два узла местами - nums[i], nums[ma] = nums[ma], nums[i] - # Циклическое просеивание вниз - i = ma - end - end - - # ## Сортировка кучей ### + ### Сортировка кучей ### def heap_sort(nums) # Построение кучи: выполнить heapify для всех узлов, кроме листовых (nums.length / 2 - 1).downto(0) do |i| diff --git a/ru/docs/chapter_sorting/insertion_sort.md b/ru/docs/chapter_sorting/insertion_sort.md index 928b0b999..3978d06bc 100644 --- a/ru/docs/chapter_sorting/insertion_sort.md +++ b/ru/docs/chapter_sorting/insertion_sort.md @@ -253,13 +253,7 @@ comments: true === "Ruby" ```ruby title="insertion_sort.rb" - =begin - File: insertion_sort.rb - Created Time: 2024-04-02 - Author: Cy (3739004@gmail.com), Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Сортировка вставками ### + ### Сортировка вставками ### def insertion_sort(nums) n = nums.length # Внешний цикл: отсортированный диапазон [0, i-1] diff --git a/ru/docs/chapter_sorting/merge_sort.md b/ru/docs/chapter_sorting/merge_sort.md index 5df7204ef..bf1011559 100644 --- a/ru/docs/chapter_sorting/merge_sort.md +++ b/ru/docs/chapter_sorting/merge_sort.md @@ -630,13 +630,7 @@ comments: true === "Ruby" ```ruby title="merge_sort.rb" - =begin - File: merge_sort.rb - Created Time: 2024-04-10 - Author: junminhong (junminhong1110@gmail.com) - =end - - # ## Слияние левого и правого подмассивов ### + ### Слияние левого и правого подмассивов ### def merge(nums, left, mid, right) # Интервал левого подмассива: [left, mid], правого подмассива: [mid+1, right] # Создать временный массив tmp для хранения результата слияния @@ -671,48 +665,7 @@ comments: true end end - =begin - File: merge_sort.rb - Created Time: 2024-04-10 - Author: junminhong (junminhong1110@gmail.com) - =end - - # ## Слияние левого и правого подмассивов ### - def merge(nums, left, mid, right) - # Интервал левого подмассива: [left, mid], правого подмассива: [mid+1, right] - # Создать временный массив tmp для хранения результата слияния - tmp = Array.new(right - left + 1, 0) - # Инициализировать начальные индексы левого и правого подмассивов - i, j, k = left, mid + 1, 0 - # Пока в левом и правом подмассивах еще есть элементы, сравнивать их и копировать меньший во временный массив - while i <= mid && j <= right - if nums[i] <= nums[j] - tmp[k] = nums[i] - i += 1 - else - tmp[k] = nums[j] - j += 1 - end - k += 1 - end - # Скопировать оставшиеся элементы левого и правого подмассивов во временный массив - while i <= mid - tmp[k] = nums[i] - i += 1 - k += 1 - end - while j <= right - tmp[k] = nums[j] - j += 1 - k += 1 - end - # Скопировать элементы временного массива tmp обратно в соответствующий диапазон исходного массива nums - (0...tmp.length).each do |k| - nums[left + k] = tmp[k] - end - end - - # ## Сортировка слиянием ### + ### Сортировка слиянием ### def merge_sort(nums, left, right) # Условие завершения # Когда длина подмассива равна 1, рекурсия завершается diff --git a/ru/docs/chapter_sorting/quick_sort.md b/ru/docs/chapter_sorting/quick_sort.md index b94197546..4d32633e0 100644 --- a/ru/docs/chapter_sorting/quick_sort.md +++ b/ru/docs/chapter_sorting/quick_sort.md @@ -346,16 +346,7 @@ comments: true === "Ruby" ```ruby title="quick_sort.rb" -=begin -File: quick_sort.rb -Created Time: 2024-04-01 -Author: Cy (3739004@gmail.com), Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) -=end - -# ## Класс быстрой сортировки ### -class QuickSort - class << self - # ## Разбиение с опорными указателями ### + ### Разбиение с опорными указателями ### def partition(nums, left, right) # Взять nums[left] в качестве опорного элемента i, j = left, right @@ -588,35 +579,7 @@ class QuickSort === "Ruby" ```ruby title="quick_sort.rb" -=begin -File: quick_sort.rb -Created Time: 2024-04-01 -Author: Cy (3739004@gmail.com), Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) -=end - -# ## Класс быстрой сортировки ### -class QuickSort - class << self - # ## Разбиение с опорными указателями ### - def partition(nums, left, right) - # Взять nums[left] в качестве опорного элемента - i, j = left, right - while i < j - while i < j && nums[j] >= nums[left] - j -= 1 # Идти справа налево в поисках первого элемента меньше опорного - end - while i < j && nums[i] <= nums[left] - i += 1 # Идти слева направо в поисках первого элемента больше опорного - end - # Обмен элементов - nums[i], nums[j] = nums[j], nums[i] - end - # Переместить опорный элемент на границу двух подмассивов - nums[i], nums[left] = nums[left], nums[i] - i # Вернуть индекс опорного элемента - end - - # ## Класс быстрой сортировки ### + ### Класс быстрой сортировки ### def quick_sort(nums, left, right) # Рекурсивно обрабатывать, пока длина подмассива не станет равной 1 if left < right @@ -1085,53 +1048,7 @@ class QuickSort === "Ruby" ```ruby title="quick_sort.rb" -=begin -File: quick_sort.rb -Created Time: 2024-04-01 -Author: Cy (3739004@gmail.com), Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) -=end - -# ## Класс быстрой сортировки ### -class QuickSort - class << self - # ## Разбиение с опорными указателями ### - def partition(nums, left, right) - # Взять nums[left] в качестве опорного элемента - i, j = left, right - while i < j - while i < j && nums[j] >= nums[left] - j -= 1 # Идти справа налево в поисках первого элемента меньше опорного - end - while i < j && nums[i] <= nums[left] - i += 1 # Идти слева направо в поисках первого элемента больше опорного - end - # Обмен элементов - nums[i], nums[j] = nums[j], nums[i] - end - # Переместить опорный элемент на границу двух подмассивов - nums[i], nums[left] = nums[left], nums[i] - i # Вернуть индекс опорного элемента - end - - # ## Класс быстрой сортировки ### - def quick_sort(nums, left, right) - # Рекурсивно обрабатывать, пока длина подмассива не станет равной 1 - if left < right - # Разбиение с опорными указателями - pivot = partition(nums, left, right) - # Рекурсивно обработать левый и правый подмассивы - quick_sort(nums, left, pivot - 1) - quick_sort(nums, pivot + 1, right) - end - nums - end - end -end - -# ## Класс быстрой сортировки (оптимизация медианой) ### -class QuickSortMedian - class << self - # ## Выбрать медиану из трех кандидатов ### + ### Выбрать медиану из трех кандидатов ### def median_three(nums, left, mid, right) # Выбрать медиану из трех кандидатов _l, _m, _r = nums[left], nums[mid], nums[right] @@ -1142,66 +1059,9 @@ class QuickSortMedian return right end -=begin -File: quick_sort.rb -Created Time: 2024-04-01 -Author: Cy (3739004@gmail.com), Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) -=end - -# ## Класс быстрой сортировки ### -class QuickSort - class << self - # ## Разбиение с опорными указателями ### + ### Разбиение с опорными указателями (медиана трех) ### def partition(nums, left, right) - # Взять nums[left] в качестве опорного элемента - i, j = left, right - while i < j - while i < j && nums[j] >= nums[left] - j -= 1 # Идти справа налево в поисках первого элемента меньше опорного - end - while i < j && nums[i] <= nums[left] - i += 1 # Идти слева направо в поисках первого элемента больше опорного - end - # Обмен элементов - nums[i], nums[j] = nums[j], nums[i] - end - # Переместить опорный элемент на границу двух подмассивов - nums[i], nums[left] = nums[left], nums[i] - i # Вернуть индекс опорного элемента - end - - # ## Класс быстрой сортировки ### - def quick_sort(nums, left, right) - # Рекурсивно обрабатывать, пока длина подмассива не станет равной 1 - if left < right - # Разбиение с опорными указателями - pivot = partition(nums, left, right) - # Рекурсивно обработать левый и правый подмассивы - quick_sort(nums, left, pivot - 1) - quick_sort(nums, pivot + 1, right) - end - nums - end - end -end - -# ## Класс быстрой сортировки (оптимизация медианой) ### -class QuickSortMedian - class << self - # ## Выбрать медиану из трех кандидатов ### - def median_three(nums, left, mid, right) - # Выбрать медиану из трех кандидатов - _l, _m, _r = nums[left], nums[mid], nums[right] - # m находится между l и r - return mid if (_l <= _m && _m <= _r) || (_r <= _m && _m <= _l) - # l находится между m и r - return left if (_m <= _l && _l <= _r) || (_r <= _l && _l <= _m) - return right - end - - # ## Разбиение с опорными указателями (медиана трех) ### - def partition(nums, left, right) - # ## Использовать nums[left] как опорный элемент + ### Использовать nums[left] как опорный элемент med = median_three(nums, left, (left + right) / 2, right) # Переместить медиану в крайний левый элемент массива nums[left], nums[med] = nums[med], nums[left] @@ -1493,124 +1353,7 @@ class QuickSortMedian === "Ruby" ```ruby title="quick_sort.rb" -=begin -File: quick_sort.rb -Created Time: 2024-04-01 -Author: Cy (3739004@gmail.com), Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) -=end - -# ## Класс быстрой сортировки ### -class QuickSort - class << self - # ## Разбиение с опорными указателями ### - def partition(nums, left, right) - # Взять nums[left] в качестве опорного элемента - i, j = left, right - while i < j - while i < j && nums[j] >= nums[left] - j -= 1 # Идти справа налево в поисках первого элемента меньше опорного - end - while i < j && nums[i] <= nums[left] - i += 1 # Идти слева направо в поисках первого элемента больше опорного - end - # Обмен элементов - nums[i], nums[j] = nums[j], nums[i] - end - # Переместить опорный элемент на границу двух подмассивов - nums[i], nums[left] = nums[left], nums[i] - i # Вернуть индекс опорного элемента - end - - # ## Класс быстрой сортировки ### - def quick_sort(nums, left, right) - # Рекурсивно обрабатывать, пока длина подмассива не станет равной 1 - if left < right - # Разбиение с опорными указателями - pivot = partition(nums, left, right) - # Рекурсивно обработать левый и правый подмассивы - quick_sort(nums, left, pivot - 1) - quick_sort(nums, pivot + 1, right) - end - nums - end - end -end - -# ## Класс быстрой сортировки (оптимизация медианой) ### -class QuickSortMedian - class << self - # ## Выбрать медиану из трех кандидатов ### - def median_three(nums, left, mid, right) - # Выбрать медиану из трех кандидатов - _l, _m, _r = nums[left], nums[mid], nums[right] - # m находится между l и r - return mid if (_l <= _m && _m <= _r) || (_r <= _m && _m <= _l) - # l находится между m и r - return left if (_m <= _l && _l <= _r) || (_r <= _l && _l <= _m) - return right - end - - # ## Разбиение с опорными указателями (медиана трех) ### - def partition(nums, left, right) - # ## Использовать nums[left] как опорный элемент - med = median_three(nums, left, (left + right) / 2, right) - # Переместить медиану в крайний левый элемент массива - nums[left], nums[med] = nums[med], nums[left] - i, j = left, right - while i < j - while i < j && nums[j] >= nums[left] - j -= 1 # Идти справа налево в поисках первого элемента меньше опорного - end - while i < j && nums[i] <= nums[left] - i += 1 # Идти слева направо в поисках первого элемента больше опорного - end - # Обмен элементов - nums[i], nums[j] = nums[j], nums[i] - end - # Переместить опорный элемент на границу двух подмассивов - nums[i], nums[left] = nums[left], nums[i] - i # Вернуть индекс опорного элемента - end - - # ## Быстрая сортировка ### - def quick_sort(nums, left, right) - # Рекурсивно обрабатывать, пока длина подмассива не станет равной 1 - if left < right - # Разбиение с опорными указателями - pivot = partition(nums, left, right) - # Рекурсивно обработать левый и правый подмассивы - quick_sort(nums, left, pivot - 1) - quick_sort(nums, pivot + 1, right) - end - nums - end - end -end - -# ## Класс быстрой сортировки (оптимизация глубины рекурсии) ### -class QuickSortTailCall - class << self - # ## Разбиение с опорными указателями ### - def partition(nums, left, right) - # Использовать nums[left] как опорный элемент - i = left - j = right - while i < j - while i < j && nums[j] >= nums[left] - j -= 1 # Идти справа налево в поисках первого элемента меньше опорного - end - while i < j && nums[i] <= nums[left] - i += 1 # Идти слева направо в поисках первого элемента больше опорного - end - # Обмен элементов - nums[i], nums[j] = nums[j], nums[i] - end - # Переместить опорный элемент на границу двух подмассивов - nums[i], nums[left] = nums[left], nums[i] - i # Вернуть индекс опорного элемента - end - - # ## Быстрая сортировка (оптимизация глубины рекурсии) ### + ### Быстрая сортировка (оптимизация глубины рекурсии) ### def quick_sort(nums, left, right) # Рекурсивно обрабатывать, пока длина подмассива не станет равной 1 while left < right diff --git a/ru/docs/chapter_sorting/radix_sort.md b/ru/docs/chapter_sorting/radix_sort.md index e8d12bb7e..f7ad78691 100644 --- a/ru/docs/chapter_sorting/radix_sort.md +++ b/ru/docs/chapter_sorting/radix_sort.md @@ -669,31 +669,13 @@ $$ === "Ruby" ```ruby title="radix_sort.rb" - =begin - File: radix_sort.rb - Created Time: 2024-05-03 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Получить k-й разряд элемента num, где exp = 10^(k-1) ### + ### Получить k-й разряд элемента num, где exp = 10^(k-1) ### def digit(num, exp) # Передача exp вместо k позволяет избежать повторного выполнения дорогостоящих вычислений степени (num / exp) % 10 end - =begin - File: radix_sort.rb - Created Time: 2024-05-03 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Получить k-й разряд элемента num, где exp = 10^(k-1) ### - def digit(num, exp) - # Передача exp вместо k позволяет избежать повторного выполнения дорогостоящих вычислений степени - (num / exp) % 10 - end - - # ## Сортировка подсчетом (сортировка по k-му разряду nums) ### + ### Сортировка подсчетом (сортировка по k-му разряду nums) ### def counting_sort_digit(nums, exp) # Разряды десятичной системы лежат в диапазоне 0~9, поэтому нужен массив корзин длины 10 counter = Array.new(10, 0) @@ -717,43 +699,7 @@ $$ (0...n).each { |i| nums[i] = res[i] } end - =begin - File: radix_sort.rb - Created Time: 2024-05-03 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Получить k-й разряд элемента num, где exp = 10^(k-1) ### - def digit(num, exp) - # Передача exp вместо k позволяет избежать повторного выполнения дорогостоящих вычислений степени - (num / exp) % 10 - end - - # ## Сортировка подсчетом (сортировка по k-му разряду nums) ### - def counting_sort_digit(nums, exp) - # Разряды десятичной системы лежат в диапазоне 0~9, поэтому нужен массив корзин длины 10 - counter = Array.new(10, 0) - n = nums.length - # Подсчитать число появлений каждой цифры от 0 до 9 - for i in 0...n - d = digit(nums[i], exp) # Получить k-й разряд nums[i], обозначив его как d - counter[d] += 1 # Подсчитать число появлений цифры d - end - # Вычислить префиксные суммы и преобразовать «число появлений» в «индекс массива» - (1...10).each { |i| counter[i] += counter[i - 1] } - # Выполняя обратный проход, заполнить res элементами по статистике в корзинах - res = Array.new(n, 0) - for i in (n - 1).downto(0) - d = digit(nums[i], exp) - j = counter[d] - 1 # Получить индекс j цифры d в массиве - res[j] = nums[i] # Поместить текущий элемент по индексу j - counter[d] -= 1 # Уменьшить количество d на 1 - end - # Перезаписать исходный массив nums результатом - (0...n).each { |i| nums[i] = res[i] } - end - - # ## Поразрядная сортировка ### + ### Поразрядная сортировка ### def radix_sort(nums) # Получить максимальный элемент массива, чтобы определить максимальное число разрядов m = nums.max diff --git a/ru/docs/chapter_sorting/selection_sort.md b/ru/docs/chapter_sorting/selection_sort.md index f871cb4e8..1414656b7 100644 --- a/ru/docs/chapter_sorting/selection_sort.md +++ b/ru/docs/chapter_sorting/selection_sort.md @@ -306,13 +306,7 @@ comments: true === "Ruby" ```ruby title="selection_sort.rb" - =begin - File: selection_sort.rb - Created Time: 2024-05-03 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Сортировка выбором ### + ### Сортировка выбором ### def selection_sort(nums) n = nums.length # Внешний цикл: неотсортированный диапазон [i, n-1] diff --git a/ru/docs/chapter_stack_and_queue/deque.md b/ru/docs/chapter_stack_and_queue/deque.md index 95d39c77d..8ae262cfe 100644 --- a/ru/docs/chapter_stack_and_queue/deque.md +++ b/ru/docs/chapter_stack_and_queue/deque.md @@ -2025,54 +2025,36 @@ comments: true Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) =end - # ## Узел двусвязного списка + ### Узел двусвязного списка class ListNode attr_accessor :val attr_accessor :next # Ссылка на узел-преемник attr_accessor :prev # Ссылка на узел-предшественник - # ## Конструктор ### + ### Конструктор ### def initialize(val) @val = val end end - =begin - File: linkedlist_deque.rb - Created Time: 2024-04-06 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Узел двусвязного списка - class ListNode - attr_accessor :val - attr_accessor :next # Ссылка на узел-преемник - attr_accessor :prev # Ссылка на узел-предшественник - - # ## Конструктор ### - def initialize(val) - @val = val - end - end - - # ## Двусторонняя очередь на основе двусвязного списка ### + ### Двусторонняя очередь на основе двусвязного списка ### class LinkedListDeque - # ## Получение длины двусторонней очереди ### + ### Получение длины двусторонней очереди ### attr_reader :size - # ## Конструктор ### + ### Конструктор ### def initialize @front = nil # Головной узел front @rear = nil # Хвостовой узел rear @size = 0 # Длина двусторонней очереди end - # ## Проверка, пуста ли двусторонняя очередь ### + ### Проверка, пуста ли двусторонняя очередь ### def is_empty? size.zero? end - # ## Операция добавления в очередь ### + ### Операция добавления в очередь ### def push(num, is_front) node = ListNode.new(num) # Если связный список пуст, пусть front и rear оба указывают на node @@ -2094,17 +2076,17 @@ comments: true @size += 1 # Обновить длину очереди end - # ## Добавление в голову очереди ### + ### Добавление в голову очереди ### def push_first(num) push(num, true) end - # ## Добавление в хвост очереди ### + ### Добавление в хвост очереди ### def push_last(num) push(num, false) end - # ## Операция извлечения из очереди ### + ### Операция извлечения из очереди ### def pop(is_front) raise IndexError, 'двусторонняя очередь пуста' if is_empty? @@ -2134,31 +2116,31 @@ comments: true val end - # ## Извлечение из головы очереди ### + ### Извлечение из головы очереди ### def pop_first pop(true) end - # ## Извлечение из головы очереди ### + ### Извлечение из головы очереди ### def pop_last pop(false) end - # ## Доступ к элементу в начале очереди ### + ### Доступ к элементу в начале очереди ### def peek_first raise IndexError, 'двусторонняя очередь пуста' if is_empty? @front.val end - # ## Доступ к элементу в хвосте очереди ### + ### Доступ к элементу в хвосте очереди ### def peek_last raise IndexError, 'двусторонняя очередь пуста' if is_empty? @rear.val end - # ## Вернуть массив для вывода ### + ### Вернуть массив для вывода ### def to_array node = @front res = Array.new(size, 0) @@ -3514,35 +3496,29 @@ comments: true === "Ruby" ```ruby title="array_deque.rb" - =begin - File: array_deque.rb - Created Time: 2024-04-05 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Двусторонняя очередь на основе кольцевого массива ### + ### Двусторонняя очередь на основе кольцевого массива ### class ArrayDeque - # ## Получение длины двусторонней очереди ### + ### Получение длины двусторонней очереди ### attr_reader :size - # ## Конструктор ### + ### Конструктор ### def initialize(capacity) @nums = Array.new(capacity, 0) @front = 0 @size = 0 end - # ## Получить вместимость двусторонней очереди ### + ### Получить вместимость двусторонней очереди ### def capacity @nums.length end - # ## Проверка, пуста ли двусторонняя очередь ### + ### Проверка, пуста ли двусторонняя очередь ### def is_empty? size.zero? end - # ## Добавление в голову очереди ### + ### Добавление в голову очереди ### def push_first(num) if size == capacity puts 'Двусторонняя очередь заполнена' @@ -3557,7 +3533,7 @@ comments: true @size += 1 end - # ## Добавление в хвост очереди ### + ### Добавление в хвост очереди ### def push_last(num) if size == capacity puts 'Двусторонняя очередь заполнена' @@ -3571,7 +3547,7 @@ comments: true @size += 1 end - # ## Извлечение из головы очереди ### + ### Извлечение из головы очереди ### def pop_first num = peek_first # Указатель головы сдвигается на одну позицию назад @@ -3580,21 +3556,21 @@ comments: true num end - # ## Извлечение из хвоста очереди ### + ### Извлечение из хвоста очереди ### def pop_last num = peek_last @size -= 1 num end - # ## Доступ к элементу в начале очереди ### + ### Доступ к элементу в начале очереди ### def peek_first raise IndexError, 'двусторонняя очередь пуста' if is_empty? @nums[@front] end - # ## Доступ к элементу в хвосте очереди ### + ### Доступ к элементу в хвосте очереди ### def peek_last raise IndexError, 'двусторонняя очередь пуста' if is_empty? @@ -3603,7 +3579,7 @@ comments: true @nums[last] end - # ## Вернуть массив для вывода ### + ### Вернуть массив для вывода ### def to_array # Преобразовывать только элементы списка в пределах фактической длины res = [] @@ -3615,7 +3591,7 @@ comments: true private - # ## Вычислить индекс в кольцевом массиве ### + ### Вычислить индекс в кольцевом массиве ### def index(i) # С помощью операции взятия по модулю соединить начало и конец массива # Когда i выходит за конец массива, он возвращается в начало diff --git a/ru/docs/chapter_stack_and_queue/queue.md b/ru/docs/chapter_stack_and_queue/queue.md index c78a5e64f..257529838 100644 --- a/ru/docs/chapter_stack_and_queue/queue.md +++ b/ru/docs/chapter_stack_and_queue/queue.md @@ -1246,32 +1246,24 @@ comments: true === "Ruby" ```ruby title="linkedlist_queue.rb" - =begin - File: linkedlist_queue.rb - Created Time: 2024-04-06 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - - # ## Очередь на основе связного списка ### + ### Очередь на основе связного списка ### class LinkedListQueue - # ## Получение длины очереди ### + ### Получение длины очереди ### attr_reader :size - # ## Конструктор ### + ### Конструктор ### def initialize @front = nil # Головной узел front @rear = nil # Хвостовой узел rear @size = 0 end - # ## Проверка, пуста ли очередь ### + ### Проверка, пуста ли очередь ### def is_empty? @front.nil? end - # ## Добавление в очередь ### + ### Добавление в очередь ### def push(num) # Добавить num после хвостового узла node = ListNode.new(num) @@ -1289,7 +1281,7 @@ comments: true @size += 1 end - # ## Извлечение из очереди ### + ### Извлечение из очереди ### def pop num = peek # Удалить головной узел @@ -1298,14 +1290,14 @@ comments: true num end - # ## Доступ к элементу в начале очереди ### + ### Доступ к элементу в начале очереди ### def peek raise IndexError, 'очередь пуста' if is_empty? @front.val end - # ## Преобразовать связный список в Array и вернуть ### + ### Преобразовать связный список в Array и вернуть ### def to_array queue = [] temp = @front @@ -2228,35 +2220,29 @@ comments: true === "Ruby" ```ruby title="array_queue.rb" - =begin - File: array_queue.rb - Created Time: 2024-04-05 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Очередь на основе кольцевого массива ### + ### Очередь на основе кольцевого массива ### class ArrayQueue - # ## Получение длины очереди ### + ### Получение длины очереди ### attr_reader :size - # ## Конструктор ### + ### Конструктор ### def initialize(size) @nums = Array.new(size, 0) # Массив для хранения элементов очереди @front = 0 # Указатель head, указывающий на первый элемент очереди @size = 0 # Длина очереди end - # ## Получить вместимость очереди ### + ### Получить вместимость очереди ### def capacity @nums.length end - # ## Проверка, пуста ли очередь ### + ### Проверка, пуста ли очередь ### def is_empty? size.zero? end - # ## Добавление в очередь ### + ### Добавление в очередь ### def push(num) raise IndexError, 'очередь заполнена' if size == capacity @@ -2268,7 +2254,7 @@ comments: true @size += 1 end - # ## Извлечение из очереди ### + ### Извлечение из очереди ### def pop num = peek # Указатель head сдвигается на одну позицию назад; если он выходит за конец, то возвращается в начало массива @@ -2277,14 +2263,14 @@ comments: true num end - # ## Доступ к элементу в начале очереди ### + ### Доступ к элементу в начале очереди ### def peek raise IndexError, 'очередь пуста' if is_empty? @nums[@front] end - # ## Вернуть список для вывода ### + ### Вернуть список для вывода ### def to_array res = Array.new(size, 0) j = @front diff --git a/ru/docs/chapter_stack_and_queue/stack.md b/ru/docs/chapter_stack_and_queue/stack.md index f8c196a89..038581520 100644 --- a/ru/docs/chapter_stack_and_queue/stack.md +++ b/ru/docs/chapter_stack_and_queue/stack.md @@ -1109,29 +1109,21 @@ comments: true === "Ruby" ```ruby title="linkedlist_stack.rb" - =begin - File: linkedlist_stack.rb - Created Time: 2024-04-06 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/list_node' - - # ## Стек на основе связного списка ### + ### Стек на основе связного списка ### class LinkedListStack attr_reader :size - # ## Конструктор ### + ### Конструктор ### def initialize @size = 0 end - # ## Проверка, пуст ли стек ### + ### Проверка, пуст ли стек ### def is_empty? @peek.nil? end - # ## Помещение в стек ### + ### Помещение в стек ### def push(val) node = ListNode.new(val) node.next = @peek @@ -1139,7 +1131,7 @@ comments: true @size += 1 end - # ## Извлечение из стека ### + ### Извлечение из стека ### def pop num = peek @peek = @peek.next @@ -1147,14 +1139,14 @@ comments: true num end - # ## Доступ к верхнему элементу стека ### + ### Доступ к верхнему элементу стека ### def peek raise IndexError, 'стек пуст' if is_empty? @peek.val end - # ## Преобразовать связный список в Array и вернуть ### + ### Преобразовать связный список в Array и вернуть ### def to_array arr = [] node = @peek @@ -1766,49 +1758,43 @@ comments: true === "Ruby" ```ruby title="array_stack.rb" - =begin - File: array_stack.rb - Created Time: 2024-04-06 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - # ## Стек на основе массива ### + ### Стек на основе массива ### class ArrayStack - # ## Конструктор ### + ### Конструктор ### def initialize @stack = [] end - # ## Получить длину стека ### + ### Получить длину стека ### def size @stack.length end - # ## Проверка, пуст ли стек ### + ### Проверка, пуст ли стек ### def is_empty? @stack.empty? end - # ## Помещение в стек ### + ### Помещение в стек ### def push(item) @stack << item end - # ## Извлечение из стека ### + ### Извлечение из стека ### def pop raise IndexError, 'стек пуст' if is_empty? @stack.pop end - # ## Доступ к верхнему элементу стека ### + ### Доступ к верхнему элементу стека ### def peek raise IndexError, 'стек пуст' if is_empty? @stack.last end - # ## Вернуть список для вывода ### + ### Вернуть список для вывода ### def to_array @stack end diff --git a/ru/docs/chapter_tree/array_representation_of_tree.md b/ru/docs/chapter_tree/array_representation_of_tree.md index c1e77ab01..e09bd4464 100644 --- a/ru/docs/chapter_tree/array_representation_of_tree.md +++ b/ru/docs/chapter_tree/array_representation_of_tree.md @@ -1245,28 +1245,19 @@ comments: true === "Ruby" ```ruby title="array_binary_tree.rb" - =begin - File: array_binary_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Класс двоичного дерева в массивном представлении ### + ### Класс двоичного дерева в массивном представлении ### class ArrayBinaryTree - # ## Конструктор ### + ### Конструктор ### def initialize(arr) @tree = arr.to_a end - # ## Вместимость списка ### + ### Вместимость списка ### def size @tree.length end - # ## Получить значение узла с индексом i ### + ### Получить значение узла с индексом i ### def val(i) # Если индекс выходит за границы, вернуть nil, обозначающий пустую ячейку return if i < 0 || i >= size @@ -1274,22 +1265,22 @@ comments: true @tree[i] end - # ## Получить индекс левого дочернего узла узла с индексом i ### + ### Получить индекс левого дочернего узла узла с индексом i ### def left(i) 2 * i + 1 end - # ## Получить индекс правого дочернего узла узла с индексом i ### + ### Получить индекс правого дочернего узла узла с индексом i ### def right(i) 2 * i + 2 end - # ## Получить индекс родительского узла узла с индексом i ### + ### Получить индекс родительского узла узла с индексом i ### def parent(i) (i - 1) / 2 end - # ## Обход в ширину ### + ### Обход в ширину ### def level_order @res = [] @@ -1301,7 +1292,7 @@ comments: true @res end - # ## Обход в глубину ### + ### Обход в глубину ### def dfs(i, order) return if val(i).nil? # Предварительный обход @@ -1314,21 +1305,21 @@ comments: true @res << val(i) if order == :post end - # ## Предварительный обход ### + ### Предварительный обход ### def pre_order @res = [] dfs(0, :pre) @res end - # ## Симметричный обход ### + ### Симметричный обход ### def in_order @res = [] dfs(0, :in) @res end - # ## Обратный обход ### + ### Обратный обход ### def post_order @res = [] dfs(0, :post) diff --git a/ru/docs/chapter_tree/avl_tree.md b/ru/docs/chapter_tree/avl_tree.md index 5a95dde28..e6390212c 100644 --- a/ru/docs/chapter_tree/avl_tree.md +++ b/ru/docs/chapter_tree/avl_tree.md @@ -460,28 +460,7 @@ AVL-дерево одновременно является и двоичным === "Ruby" ```ruby title="avl_tree.rb" - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### + ### Получить высоту узла ### def height(node) # Высота пустого узла равна -1, высота листового узла равна 0 return node.height unless node.nil? @@ -489,36 +468,7 @@ AVL-дерево одновременно является и двоичным -1 end - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### + ### Обновить высоту узла ### def update_height(node) # Высота узла равна высоте более высокого поддерева + 1 node.height = [height(node.left), height(node.right)].max + 1 @@ -686,42 +636,7 @@ AVL-дерево одновременно является и двоичным === "Ruby" ```ruby title="avl_tree.rb" - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### - def update_height(node) - # Высота узла равна высоте более высокого поддерева + 1 - node.height = [height(node.left), height(node.right)].max + 1 - end - - # ## Получить коэффициент баланса ### + ### Получить коэффициент баланса ### def balance_factor(node) # Коэффициент баланса пустого узла равен 0 return 0 if node.nil? @@ -991,51 +906,7 @@ AVL-дерево одновременно является и двоичным === "Ruby" ```ruby title="avl_tree.rb" - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### - def update_height(node) - # Высота узла равна высоте более высокого поддерева + 1 - node.height = [height(node.left), height(node.right)].max + 1 - end - - # ## Получить коэффициент баланса ### - def balance_factor(node) - # Коэффициент баланса пустого узла равен 0 - return 0 if node.nil? - - # Коэффициент баланса узла = высота левого поддерева - высота правого поддерева - height(node.left) - height(node.right) - end - - # ## Операция правого вращения ### + ### Операция правого вращения ### def right_rotate(node) child = node.left grand_child = child.right @@ -1290,65 +1161,7 @@ AVL-дерево одновременно является и двоичным === "Ruby" ```ruby title="avl_tree.rb" - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### - def update_height(node) - # Высота узла равна высоте более высокого поддерева + 1 - node.height = [height(node.left), height(node.right)].max + 1 - end - - # ## Получить коэффициент баланса ### - def balance_factor(node) - # Коэффициент баланса пустого узла равен 0 - return 0 if node.nil? - - # Коэффициент баланса узла = высота левого поддерева - высота правого поддерева - height(node.left) - height(node.right) - end - - # ## Операция правого вращения ### - def right_rotate(node) - child = node.left - grand_child = child.right - # Выполнить правое вращение узла node вокруг child - child.right = node - node.left = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Операция левого вращения ### + ### Операция левого вращения ### def left_rotate(node) child = node.right grand_child = child.left @@ -1816,79 +1629,7 @@ AVL-дерево одновременно является и двоичным === "Ruby" ```ruby title="avl_tree.rb" - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### - def update_height(node) - # Высота узла равна высоте более высокого поддерева + 1 - node.height = [height(node.left), height(node.right)].max + 1 - end - - # ## Получить коэффициент баланса ### - def balance_factor(node) - # Коэффициент баланса пустого узла равен 0 - return 0 if node.nil? - - # Коэффициент баланса узла = высота левого поддерева - высота правого поддерева - height(node.left) - height(node.right) - end - - # ## Операция правого вращения ### - def right_rotate(node) - child = node.left - grand_child = child.right - # Выполнить правое вращение узла node вокруг child - child.right = node - node.left = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Операция левого вращения ### - def left_rotate(node) - child = node.right - grand_child = child.left - # Выполнить левое вращение узла node вокруг child - child.left = node - node.right = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Выполнить вращение, чтобы снова сбалансировать поддерево ### + ### Выполнить вращение, чтобы снова сбалансировать поддерево ### def rotate(node) # Получить коэффициент баланса узла node balance_factor = balance_factor(node) @@ -2272,219 +2013,12 @@ AVL-дерево одновременно является и двоичным === "Ruby" ```ruby title="avl_tree.rb" - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### - def update_height(node) - # Высота узла равна высоте более высокого поддерева + 1 - node.height = [height(node.left), height(node.right)].max + 1 - end - - # ## Получить коэффициент баланса ### - def balance_factor(node) - # Коэффициент баланса пустого узла равен 0 - return 0 if node.nil? - - # Коэффициент баланса узла = высота левого поддерева - высота правого поддерева - height(node.left) - height(node.right) - end - - # ## Операция правого вращения ### - def right_rotate(node) - child = node.left - grand_child = child.right - # Выполнить правое вращение узла node вокруг child - child.right = node - node.left = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Операция левого вращения ### - def left_rotate(node) - child = node.right - grand_child = child.left - # Выполнить левое вращение узла node вокруг child - child.left = node - node.right = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Выполнить вращение, чтобы снова сбалансировать поддерево ### - def rotate(node) - # Получить коэффициент баланса узла node - balance_factor = balance_factor(node) - # Обойти левое поддерево - if balance_factor > 1 - if balance_factor(node.left) >= 0 - # Правое вращение - return right_rotate(node) - else - # Сначала левое вращение, затем правое - node.left = left_rotate(node.left) - return right_rotate(node) - end - # Правостороннее дерево обхода - elsif balance_factor < -1 - if balance_factor(node.right) <= 0 - # Левое вращение - return left_rotate(node) - else - # Сначала правое вращение, затем левое - node.right = right_rotate(node.right) - return left_rotate(node) - end - end - # Дерево сбалансировано, вращение не требуется, вернуть сразу - node - end - - # ## Вставка узла ### + ### Вставка узла ### def insert(val) @root = insert_helper(@root, val) end - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### - def update_height(node) - # Высота узла равна высоте более высокого поддерева + 1 - node.height = [height(node.left), height(node.right)].max + 1 - end - - # ## Получить коэффициент баланса ### - def balance_factor(node) - # Коэффициент баланса пустого узла равен 0 - return 0 if node.nil? - - # Коэффициент баланса узла = высота левого поддерева - высота правого поддерева - height(node.left) - height(node.right) - end - - # ## Операция правого вращения ### - def right_rotate(node) - child = node.left - grand_child = child.right - # Выполнить правое вращение узла node вокруг child - child.right = node - node.left = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Операция левого вращения ### - def left_rotate(node) - child = node.right - grand_child = child.left - # Выполнить левое вращение узла node вокруг child - child.left = node - node.right = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Выполнить вращение, чтобы снова сбалансировать поддерево ### - def rotate(node) - # Получить коэффициент баланса узла node - balance_factor = balance_factor(node) - # Обойти левое поддерево - if balance_factor > 1 - if balance_factor(node.left) >= 0 - # Правое вращение - return right_rotate(node) - else - # Сначала левое вращение, затем правое - node.left = left_rotate(node.left) - return right_rotate(node) - end - # Правостороннее дерево обхода - elsif balance_factor < -1 - if balance_factor(node.right) <= 0 - # Левое вращение - return left_rotate(node) - else - # Сначала правое вращение, затем левое - node.right = right_rotate(node.right) - return left_rotate(node) - end - end - # Дерево сбалансировано, вращение не требуется, вернуть сразу - node - end - - # ## Вставка узла ### - def insert(val) - @root = insert_helper(@root, val) - end - - # ## Рекурсивная вставка узла (вспомогательный метод) ### + ### Рекурсивная вставка узла (вспомогательный метод) ### def insert_helper(node, val) return TreeNode.new(val) if node.nil? # 1. Найти позицию вставки и вставить узел @@ -3067,265 +2601,12 @@ AVL-дерево одновременно является и двоичным === "Ruby" ```ruby title="avl_tree.rb" - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### - def update_height(node) - # Высота узла равна высоте более высокого поддерева + 1 - node.height = [height(node.left), height(node.right)].max + 1 - end - - # ## Получить коэффициент баланса ### - def balance_factor(node) - # Коэффициент баланса пустого узла равен 0 - return 0 if node.nil? - - # Коэффициент баланса узла = высота левого поддерева - высота правого поддерева - height(node.left) - height(node.right) - end - - # ## Операция правого вращения ### - def right_rotate(node) - child = node.left - grand_child = child.right - # Выполнить правое вращение узла node вокруг child - child.right = node - node.left = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Операция левого вращения ### - def left_rotate(node) - child = node.right - grand_child = child.left - # Выполнить левое вращение узла node вокруг child - child.left = node - node.right = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Выполнить вращение, чтобы снова сбалансировать поддерево ### - def rotate(node) - # Получить коэффициент баланса узла node - balance_factor = balance_factor(node) - # Обойти левое поддерево - if balance_factor > 1 - if balance_factor(node.left) >= 0 - # Правое вращение - return right_rotate(node) - else - # Сначала левое вращение, затем правое - node.left = left_rotate(node.left) - return right_rotate(node) - end - # Правостороннее дерево обхода - elsif balance_factor < -1 - if balance_factor(node.right) <= 0 - # Левое вращение - return left_rotate(node) - else - # Сначала правое вращение, затем левое - node.right = right_rotate(node.right) - return left_rotate(node) - end - end - # Дерево сбалансировано, вращение не требуется, вернуть сразу - node - end - - # ## Вставка узла ### - def insert(val) - @root = insert_helper(@root, val) - end - - # ## Рекурсивная вставка узла (вспомогательный метод) ### - def insert_helper(node, val) - return TreeNode.new(val) if node.nil? - # 1. Найти позицию вставки и вставить узел - if val < node.val - node.left = insert_helper(node.left, val) - elsif val > node.val - node.right = insert_helper(node.right, val) - else - # Повторяющийся узел не вставлять, сразу вернуть - return node - end - # Обновить высоту узла - update_height(node) - # 2. Выполнить вращение, чтобы снова сбалансировать поддерево - rotate(node) - end - - # ## Удаление узла ### + ### Удаление узла ### def remove(val) @root = remove_helper(@root, val) end - =begin - File: avl_tree.rb - Created Time: 2024-04-17 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## AVL-дерево ### - class AVLTree - # ## Конструктор ### - def initialize - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Получить высоту узла ### - def height(node) - # Высота пустого узла равна -1, высота листового узла равна 0 - return node.height unless node.nil? - - -1 - end - - # ## Обновить высоту узла ### - def update_height(node) - # Высота узла равна высоте более высокого поддерева + 1 - node.height = [height(node.left), height(node.right)].max + 1 - end - - # ## Получить коэффициент баланса ### - def balance_factor(node) - # Коэффициент баланса пустого узла равен 0 - return 0 if node.nil? - - # Коэффициент баланса узла = высота левого поддерева - высота правого поддерева - height(node.left) - height(node.right) - end - - # ## Операция правого вращения ### - def right_rotate(node) - child = node.left - grand_child = child.right - # Выполнить правое вращение узла node вокруг child - child.right = node - node.left = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Операция левого вращения ### - def left_rotate(node) - child = node.right - grand_child = child.left - # Выполнить левое вращение узла node вокруг child - child.left = node - node.right = grand_child - # Обновить высоту узла - update_height(node) - update_height(child) - # Вернуть корневой узел поддерева после вращения - child - end - - # ## Выполнить вращение, чтобы снова сбалансировать поддерево ### - def rotate(node) - # Получить коэффициент баланса узла node - balance_factor = balance_factor(node) - # Обойти левое поддерево - if balance_factor > 1 - if balance_factor(node.left) >= 0 - # Правое вращение - return right_rotate(node) - else - # Сначала левое вращение, затем правое - node.left = left_rotate(node.left) - return right_rotate(node) - end - # Правостороннее дерево обхода - elsif balance_factor < -1 - if balance_factor(node.right) <= 0 - # Левое вращение - return left_rotate(node) - else - # Сначала правое вращение, затем левое - node.right = right_rotate(node.right) - return left_rotate(node) - end - end - # Дерево сбалансировано, вращение не требуется, вернуть сразу - node - end - - # ## Вставка узла ### - def insert(val) - @root = insert_helper(@root, val) - end - - # ## Рекурсивная вставка узла (вспомогательный метод) ### - def insert_helper(node, val) - return TreeNode.new(val) if node.nil? - # 1. Найти позицию вставки и вставить узел - if val < node.val - node.left = insert_helper(node.left, val) - elsif val > node.val - node.right = insert_helper(node.right, val) - else - # Повторяющийся узел не вставлять, сразу вернуть - return node - end - # Обновить высоту узла - update_height(node) - # 2. Выполнить вращение, чтобы снова сбалансировать поддерево - rotate(node) - end - - # ## Удаление узла ### - def remove(val) - @root = remove_helper(@root, val) - end - - # ## Рекурсивное удаление узла (вспомогательный метод) ### + ### Рекурсивное удаление узла (вспомогательный метод) ### def remove_helper(node, val) return if node.nil? # 1. Найти узел и удалить его diff --git a/ru/docs/chapter_tree/binary_search_tree.md b/ru/docs/chapter_tree/binary_search_tree.md index 69f51865f..2fc6cd52d 100644 --- a/ru/docs/chapter_tree/binary_search_tree.md +++ b/ru/docs/chapter_tree/binary_search_tree.md @@ -316,29 +316,7 @@ comments: true === "Ruby" ```ruby title="binary_search_tree.rb" - =begin - File: binary_search_tree.rb - Created Time: 2024-04-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Двоичное дерево поиска ### - class BinarySearchTree - # ## Конструктор ### - def initialize - # Инициализировать пустое дерево - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Поиск узла ### + ### Поиск узла ### def search(num) cur = @root @@ -790,50 +768,7 @@ comments: true === "Ruby" ```ruby title="binary_search_tree.rb" - =begin - File: binary_search_tree.rb - Created Time: 2024-04-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Двоичное дерево поиска ### - class BinarySearchTree - # ## Конструктор ### - def initialize - # Инициализировать пустое дерево - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Поиск узла ### - def search(num) - cur = @root - - # Искать в цикле и выйти после прохода за листовой узел - while !cur.nil? - # Целевой узел находится в правом поддереве cur - if cur.val < num - cur = cur.right - # Целевой узел находится в левом поддереве cur - elsif cur.val > num - cur = cur.left - # Найти целевой узел и выйти из цикла - else - break - end - end - - cur - end - - # ## Вставка узла ### + ### Вставка узла ### def insert(num) # Если дерево пусто, инициализировать корневой узел if @root.nil? @@ -1600,83 +1535,7 @@ comments: true === "Ruby" ```ruby title="binary_search_tree.rb" - =begin - File: binary_search_tree.rb - Created Time: 2024-04-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Двоичное дерево поиска ### - class BinarySearchTree - # ## Конструктор ### - def initialize - # Инициализировать пустое дерево - @root = nil - end - - # ## Получение корневого узла двоичного дерева ### - def get_root - @root - end - - # ## Поиск узла ### - def search(num) - cur = @root - - # Искать в цикле и выйти после прохода за листовой узел - while !cur.nil? - # Целевой узел находится в правом поддереве cur - if cur.val < num - cur = cur.right - # Целевой узел находится в левом поддереве cur - elsif cur.val > num - cur = cur.left - # Найти целевой узел и выйти из цикла - else - break - end - end - - cur - end - - # ## Вставка узла ### - def insert(num) - # Если дерево пусто, инициализировать корневой узел - if @root.nil? - @root = TreeNode.new(num) - return - end - - # Искать в цикле и выйти после прохода за листовой узел - cur, pre = @root, nil - while !cur.nil? - # Найти повторяющийся узел и сразу вернуть - return if cur.val == num - - pre = cur - # Позиция вставки находится в правом поддереве cur - if cur.val < num - cur = cur.right - # Позиция вставки находится в левом поддереве cur - else - cur = cur.left - end - end - - # Вставка узла - node = TreeNode.new(num) - if pre.val < num - pre.right = node - else - pre.left = node - end - end - - # ## Удаление узла ### + ### Удаление узла ### def remove(num) # Если дерево пусто, сразу вернуть return if @root.nil? diff --git a/ru/docs/chapter_tree/binary_tree_traversal.md b/ru/docs/chapter_tree/binary_tree_traversal.md index 19b4ea256..4b4d4e882 100644 --- a/ru/docs/chapter_tree/binary_tree_traversal.md +++ b/ru/docs/chapter_tree/binary_tree_traversal.md @@ -318,16 +318,7 @@ comments: true === "Ruby" ```ruby title="binary_tree_bfs.rb" - =begin - File: binary_tree_bfs.rb - Created Time: 2024-04-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Обход в ширину ### + ### Обход в ширину ### def level_order(root) # Инициализировать очередь и добавить корневой узел queue = [root] @@ -797,16 +788,7 @@ comments: true === "Ruby" ```ruby title="binary_tree_dfs.rb" - =begin - File: binary_tree_dfs.rb - Created Time: 2024-04-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Предварительный обход ### + ### Предварительный обход ### def pre_order(root) return if root.nil? @@ -816,26 +798,7 @@ comments: true pre_order(root.right) end - =begin - File: binary_tree_dfs.rb - Created Time: 2024-04-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Предварительный обход ### - def pre_order(root) - return if root.nil? - - # Порядок обхода: корень -> левое поддерево -> правое поддерево - $res << root.val - pre_order(root.left) - pre_order(root.right) - end - - # ## Симметричный обход ### + ### Симметричный обход ### def in_order(root) return if root.nil? @@ -845,36 +808,7 @@ comments: true in_order(root.right) end - =begin - File: binary_tree_dfs.rb - Created Time: 2024-04-18 - Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com) - =end - - require_relative '../utils/tree_node' - require_relative '../utils/print_util' - - # ## Предварительный обход ### - def pre_order(root) - return if root.nil? - - # Порядок обхода: корень -> левое поддерево -> правое поддерево - $res << root.val - pre_order(root.left) - pre_order(root.right) - end - - # ## Симметричный обход ### - def in_order(root) - return if root.nil? - - # Порядок обхода: левое поддерево -> корень -> правое поддерево - in_order(root.left) - $res << root.val - in_order(root.right) - end - - # ## Обратный обход ### + ### Обратный обход ### def post_order(root) return if root.nil?