mirror of
https://github.com/krahets/hello-algo.git
synced 2026-08-19 23:10:58 +00:00
build
This commit is contained in:
@@ -307,13 +307,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array.rb"
|
```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)
|
def random_access(nums)
|
||||||
# Случайным образом выбрать число из интервала [0, nums.length)
|
# Случайным образом выбрать число из интервала [0, nums.length)
|
||||||
random_index = Random.rand(0...nums.length)
|
random_index = Random.rand(0...nums.length)
|
||||||
@@ -507,39 +501,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array.rb"
|
```ruby title="array.rb"
|
||||||
=begin
|
### Вставка элемента num по индексу index в массив ###
|
||||||
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)
|
def insert(nums, num, index)
|
||||||
# Сдвинуть элемент с индексом index и все последующие элементы на одну позицию назад
|
# Сдвинуть элемент с индексом index и все последующие элементы на одну позицию назад
|
||||||
for i in (nums.length - 1).downto(index + 1)
|
for i in (nums.length - 1).downto(index + 1)
|
||||||
@@ -712,51 +674,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array.rb"
|
```ruby title="array.rb"
|
||||||
=begin
|
### Удаление элемента по индексу index ###
|
||||||
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)
|
def remove(nums, index)
|
||||||
# Сдвинуть все элементы после индекса index на одну позицию вперед
|
# Сдвинуть все элементы после индекса index на одну позицию вперед
|
||||||
for i in index...(nums.length - 1)
|
for i in index...(nums.length - 1)
|
||||||
@@ -996,59 +914,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array.rb"
|
```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)
|
def traverse(nums)
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
@@ -1236,74 +1102,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array.rb"
|
```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)
|
def find(nums, target)
|
||||||
for i in 0...nums.length
|
for i in 0...nums.length
|
||||||
return i if nums[i] == target
|
return i if nums[i] == target
|
||||||
@@ -1526,23 +1325,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array.rb"
|
```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 в Ruby является динамическим массивом и может быть расширен напрямую
|
||||||
# Для удобства обучения эта функция рассматривает Array как массив неизменяемой длины
|
# Для удобства обучения эта функция рассматривает Array как массив неизменяемой длины
|
||||||
def extend(nums, enlarge)
|
def extend(nums, enlarge)
|
||||||
|
|||||||
@@ -570,16 +570,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="linked_list.rb"
|
```ruby title="linked_list.rb"
|
||||||
=begin
|
### Вставка узла _p после узла n0 в связном списке ###
|
||||||
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`
|
# В Ruby `p` — встроенная функция, а `P` — константа, поэтому вместо этого можно использовать `_p`
|
||||||
def insert(n0, _p)
|
def insert(n0, _p)
|
||||||
n1 = n0.next
|
n1 = n0.next
|
||||||
@@ -780,24 +771,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="linked_list.rb"
|
```ruby title="linked_list.rb"
|
||||||
=begin
|
### Удаление первого узла после узла n0 в связном списке ###
|
||||||
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)
|
def remove(n0)
|
||||||
return if n0.next.nil?
|
return if n0.next.nil?
|
||||||
|
|
||||||
@@ -1001,34 +975,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="linked_list.rb"
|
```ruby title="linked_list.rb"
|
||||||
=begin
|
### Доступ к узлу связного списка по индексу index ###
|
||||||
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)
|
def access(head, index)
|
||||||
for i in 0...index
|
for i in 0...index
|
||||||
return nil if head.nil?
|
return nil if head.nil?
|
||||||
@@ -1252,44 +1199,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="linked_list.rb"
|
```ruby title="linked_list.rb"
|
||||||
=begin
|
### Поиск первого узла со значением target в связном списке ###
|
||||||
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 в связном списке ###
|
|
||||||
def find(head, target)
|
def find(head, target)
|
||||||
index = 0
|
index = 0
|
||||||
while head
|
while head
|
||||||
|
|||||||
@@ -2198,18 +2198,12 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="my_list.rb"
|
```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
|
class MyList
|
||||||
attr_reader :size # Получить длину списка (текущее число элементов)
|
attr_reader :size # Получить длину списка (текущее число элементов)
|
||||||
attr_reader :capacity # Получить вместимость списка
|
attr_reader :capacity # Получить вместимость списка
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize
|
def initialize
|
||||||
@capacity = 10
|
@capacity = 10
|
||||||
@size = 0
|
@size = 0
|
||||||
@@ -2217,20 +2211,20 @@ comments: true
|
|||||||
@arr = Array.new(capacity)
|
@arr = Array.new(capacity)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к элементу ###
|
### Доступ к элементу ###
|
||||||
def get(index)
|
def get(index)
|
||||||
# Если индекс выходит за границы, выбрасывается исключение; далее аналогично
|
# Если индекс выходит за границы, выбрасывается исключение; далее аналогично
|
||||||
raise IndexError, "индекс выходит за границы" if index < 0 || index >= size
|
raise IndexError, "индекс выходит за границы" if index < 0 || index >= size
|
||||||
@arr[index]
|
@arr[index]
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к элементу ###
|
### Доступ к элементу ###
|
||||||
def set(index, num)
|
def set(index, num)
|
||||||
raise IndexError, "индекс выходит за границы" if index < 0 || index >= size
|
raise IndexError, "индекс выходит за границы" if index < 0 || index >= size
|
||||||
@arr[index] = num
|
@arr[index] = num
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление элемента в конец ###
|
### Добавление элемента в конец ###
|
||||||
def add(num)
|
def add(num)
|
||||||
# При превышении вместимости по числу элементов запускается расширение
|
# При превышении вместимости по числу элементов запускается расширение
|
||||||
extend_capacity if size == capacity
|
extend_capacity if size == capacity
|
||||||
@@ -2240,7 +2234,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вставка элемента в середину ###
|
### Вставка элемента в середину ###
|
||||||
def insert(index, num)
|
def insert(index, num)
|
||||||
raise IndexError, "индекс выходит за границы" if index < 0 || index >= size
|
raise IndexError, "индекс выходит за границы" if index < 0 || index >= size
|
||||||
|
|
||||||
@@ -2257,7 +2251,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Удаление элемента ###
|
### Удаление элемента ###
|
||||||
def remove(index)
|
def remove(index)
|
||||||
raise IndexError, "индекс выходит за границы" if index < 0 || index >= size
|
raise IndexError, "индекс выходит за границы" if index < 0 || index >= size
|
||||||
num = @arr[index]
|
num = @arr[index]
|
||||||
@@ -2274,7 +2268,7 @@ comments: true
|
|||||||
num
|
num
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Расширение списка ###
|
### Расширение списка ###
|
||||||
def extend_capacity
|
def extend_capacity
|
||||||
# Создать новый массив длиной в extend_ratio раз больше исходного и скопировать в него исходный массив
|
# Создать новый массив длиной в extend_ratio раз больше исходного и скопировать в него исходный массив
|
||||||
arr = @arr.dup + Array.new(capacity * (@extend_ratio - 1))
|
arr = @arr.dup + Array.new(capacity * (@extend_ratio - 1))
|
||||||
@@ -2282,7 +2276,7 @@ comments: true
|
|||||||
@capacity = arr.length
|
@capacity = arr.length
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Преобразование списка в массив ###
|
### Преобразование списка в массив ###
|
||||||
def to_array
|
def to_array
|
||||||
sz = size
|
sz = size
|
||||||
# Преобразовывать только элементы списка в пределах фактической длины
|
# Преобразовывать только элементы списка в пределах фактической длины
|
||||||
|
|||||||
@@ -220,16 +220,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="preorder_traversal_i_compact.rb"
|
```ruby title="preorder_traversal_i_compact.rb"
|
||||||
=begin
|
### Предварительный обход: пример 1 ###
|
||||||
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 ###
|
|
||||||
def pre_order(root)
|
def pre_order(root)
|
||||||
return unless root
|
return unless root
|
||||||
|
|
||||||
@@ -534,16 +525,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="preorder_traversal_ii_compact.rb"
|
```ruby title="preorder_traversal_ii_compact.rb"
|
||||||
=begin
|
### Предварительный обход: пример 2 ###
|
||||||
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 ###
|
|
||||||
def pre_order(root)
|
def pre_order(root)
|
||||||
return unless root
|
return unless root
|
||||||
|
|
||||||
@@ -896,16 +878,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="preorder_traversal_iii_compact.rb"
|
```ruby title="preorder_traversal_iii_compact.rb"
|
||||||
=begin
|
### Предварительный обход: пример 3 ###
|
||||||
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 ###
|
|
||||||
def pre_order(root)
|
def pre_order(root)
|
||||||
# Отсечение
|
# Отсечение
|
||||||
return if !root || root.val == 3
|
return if !root || root.val == 3
|
||||||
@@ -1906,161 +1879,32 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="preorder_traversal_iii_template.rb"
|
```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)
|
def is_solution?(state)
|
||||||
!state.empty? && state.last.val == 7
|
!state.empty? && state.last.val == 7
|
||||||
end
|
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)
|
def record_solution(state, res)
|
||||||
res << state.dup
|
res << state.dup
|
||||||
end
|
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)
|
def is_valid?(state, choice)
|
||||||
choice && choice.val != 3
|
choice && choice.val != 3
|
||||||
end
|
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)
|
def make_choice(state, choice)
|
||||||
state << choice
|
state << choice
|
||||||
end
|
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)
|
def undo_choice(state, choice)
|
||||||
state.pop
|
state.pop
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Алгоритм бэктрекинга: пример 3 ###
|
||||||
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 ###
|
|
||||||
def backtrack(state, choices, res)
|
def backtrack(state, choices, res)
|
||||||
# Проверить, является ли текущее состояние решением
|
# Проверить, является ли текущее состояние решением
|
||||||
record_solution(state, res) if is_solution?(state)
|
record_solution(state, res) if is_solution?(state)
|
||||||
|
|||||||
@@ -703,13 +703,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="n_queens.rb"
|
```ruby title="n_queens.rb"
|
||||||
=begin
|
### Алгоритм бэктрекинга: n ферзей ###
|
||||||
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)
|
def backtrack(row, n, state, res, cols, diags1, diags2)
|
||||||
# Когда все строки уже обработаны, записать решение
|
# Когда все строки уже обработаны, записать решение
|
||||||
if row == n
|
if row == n
|
||||||
@@ -736,40 +730,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Решить задачу о n ферзях ###
|
||||||
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 ферзях ###
|
|
||||||
def n_queens(n)
|
def n_queens(n)
|
||||||
# Инициализировать доску размера n*n, где 'Q' обозначает ферзя, а '#' — пустую клетку
|
# Инициализировать доску размера n*n, где 'Q' обозначает ферзя, а '#' — пустую клетку
|
||||||
state = Array.new(n) { Array.new(n, "#") }
|
state = Array.new(n) { Array.new(n, "#") }
|
||||||
|
|||||||
@@ -506,13 +506,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="permutations_i.rb"
|
```ruby title="permutations_i.rb"
|
||||||
=begin
|
### Алгоритм бэктрекинга: все перестановки I ###
|
||||||
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)
|
def backtrack(state, choices, selected, res)
|
||||||
# Когда длина состояния равна числу элементов, записать решение
|
# Когда длина состояния равна числу элементов, записать решение
|
||||||
if state.length == choices.length
|
if state.length == choices.length
|
||||||
@@ -536,37 +530,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Все перестановки I ###
|
||||||
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 ###
|
|
||||||
def permutations_i(nums)
|
def permutations_i(nums)
|
||||||
res = []
|
res = []
|
||||||
backtrack([], nums, Array.new(nums.length, false), res)
|
backtrack([], nums, Array.new(nums.length, false), res)
|
||||||
@@ -1087,13 +1051,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="permutations_ii.rb"
|
```ruby title="permutations_ii.rb"
|
||||||
=begin
|
### Алгоритм бэктрекинга: все перестановки II ###
|
||||||
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)
|
def backtrack(state, choices, selected, res)
|
||||||
# Когда длина состояния равна числу элементов, записать решение
|
# Когда длина состояния равна числу элементов, записать решение
|
||||||
if state.length == choices.length
|
if state.length == choices.length
|
||||||
@@ -1119,39 +1077,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Все перестановки II ###
|
||||||
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 ###
|
|
||||||
def permutations_ii(nums)
|
def permutations_ii(nums)
|
||||||
res = []
|
res = []
|
||||||
backtrack([], nums, Array.new(nums.length, false), res)
|
backtrack([], nums, Array.new(nums.length, false), res)
|
||||||
|
|||||||
@@ -470,13 +470,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="subset_sum_i_naive.rb"
|
```ruby title="subset_sum_i_naive.rb"
|
||||||
=begin
|
### Алгоритм бэктрекинга: сумма подмножеств I ###
|
||||||
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)
|
def backtrack(state, target, total, choices, res)
|
||||||
# Если сумма подмножества равна target, записать решение
|
# Если сумма подмножества равна target, записать решение
|
||||||
if total == target
|
if total == target
|
||||||
@@ -497,34 +491,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Решить задачу суммы подмножеств I (с повторяющимися подмножествами) ###
|
||||||
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 (с повторяющимися подмножествами) ###
|
|
||||||
def subset_sum_i_naive(nums, target)
|
def subset_sum_i_naive(nums, target)
|
||||||
state = [] # Состояние (подмножество)
|
state = [] # Состояние (подмножество)
|
||||||
total = 0 # Сумма подмножеств
|
total = 0 # Сумма подмножеств
|
||||||
@@ -1062,13 +1029,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="subset_sum_i.rb"
|
```ruby title="subset_sum_i.rb"
|
||||||
=begin
|
### Алгоритм бэктрекинга: сумма подмножеств I ###
|
||||||
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)
|
def backtrack(state, target, choices, start, res)
|
||||||
# Если сумма подмножества равна target, записать решение
|
# Если сумма подмножества равна target, записать решение
|
||||||
if target.zero?
|
if target.zero?
|
||||||
@@ -1090,35 +1051,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Решить задачу суммы подмножеств I ###
|
||||||
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 ###
|
|
||||||
def subset_sum_i(nums, target)
|
def subset_sum_i(nums, target)
|
||||||
state = [] # Состояние (подмножество)
|
state = [] # Состояние (подмножество)
|
||||||
nums.sort! # Отсортировать nums
|
nums.sort! # Отсортировать nums
|
||||||
@@ -1703,13 +1636,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="subset_sum_ii.rb"
|
```ruby title="subset_sum_ii.rb"
|
||||||
=begin
|
### Алгоритм бэктрекинга: сумма подмножеств II ###
|
||||||
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)
|
def backtrack(state, target, choices, start, res)
|
||||||
# Если сумма подмножества равна target, записать решение
|
# Если сумма подмножества равна target, записать решение
|
||||||
if target.zero?
|
if target.zero?
|
||||||
@@ -1735,39 +1662,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Решить задачу суммы подмножеств II ###
|
||||||
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 ###
|
|
||||||
def subset_sum_ii(nums, target)
|
def subset_sum_ii(nums, target)
|
||||||
state = [] # Состояние (подмножество)
|
state = [] # Состояние (подмножество)
|
||||||
nums.sort! # Отсортировать nums
|
nums.sort! # Отсортировать nums
|
||||||
|
|||||||
@@ -185,13 +185,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="iteration.rb"
|
```ruby title="iteration.rb"
|
||||||
=begin
|
### Цикл for ###
|
||||||
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)
|
def for_loop(n)
|
||||||
res = 0
|
res = 0
|
||||||
|
|
||||||
@@ -419,25 +413,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="iteration.rb"
|
```ruby title="iteration.rb"
|
||||||
=begin
|
### Цикл while ###
|
||||||
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)
|
def while_loop(n)
|
||||||
res = 0
|
res = 0
|
||||||
i = 1 # Инициализация условной переменной
|
i = 1 # Инициализация условной переменной
|
||||||
@@ -680,39 +656,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="iteration.rb"
|
```ruby title="iteration.rb"
|
||||||
=begin
|
### Цикл while (двойное обновление) ###
|
||||||
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)
|
def while_loop_ii(n)
|
||||||
res = 0
|
res = 0
|
||||||
i = 1 # Инициализация условной переменной
|
i = 1 # Инициализация условной переменной
|
||||||
@@ -948,55 +892,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="iteration.rb"
|
```ruby title="iteration.rb"
|
||||||
=begin
|
### Двойной цикл for ###
|
||||||
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 ###
|
|
||||||
def nested_for_loop(n)
|
def nested_for_loop(n)
|
||||||
res = ""
|
res = ""
|
||||||
|
|
||||||
@@ -1224,13 +1120,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="recursion.rb"
|
```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)
|
def recur(n)
|
||||||
# Условие завершения
|
# Условие завершения
|
||||||
return 1 if n == 1
|
return 1 if n == 1
|
||||||
@@ -1445,43 +1335,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="recursion.rb"
|
```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)
|
def tail_recur(n, res)
|
||||||
# Условие завершения
|
# Условие завершения
|
||||||
return res if n == 0
|
return res if n == 0
|
||||||
@@ -1705,51 +1559,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="recursion.rb"
|
```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)
|
def fib(n)
|
||||||
# Условие завершения: f(1) = 0, f(2) = 1
|
# Условие завершения: f(1) = 0, f(2) = 1
|
||||||
return n - 1 if n == 1 || n == 2
|
return n - 1 if n == 1 || n == 2
|
||||||
@@ -2084,23 +1894,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="recursion.rb"
|
```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)
|
def for_loop_recur(n)
|
||||||
# Использовать явный стек для имитации системного стека вызовов
|
# Использовать явный стек для имитации системного стека вызовов
|
||||||
stack = []
|
stack = []
|
||||||
|
|||||||
@@ -1157,39 +1157,13 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="space_complexity.rb"
|
```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
|
def function
|
||||||
# Выполнить некоторые операции
|
# Выполнить некоторые операции
|
||||||
0
|
0
|
||||||
end
|
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)
|
def constant(n)
|
||||||
# Константы, переменные и объекты занимают O(1) памяти
|
# Константы, переменные и объекты занимают O(1) памяти
|
||||||
a = 0
|
a = 0
|
||||||
@@ -1468,36 +1442,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="space_complexity.rb"
|
```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)
|
def linear(n)
|
||||||
# Список длины n занимает O(n) памяти
|
# Список длины n занимает O(n) памяти
|
||||||
nums = Array.new(n, 0)
|
nums = Array.new(n, 0)
|
||||||
@@ -1662,48 +1607,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="space_complexity.rb"
|
```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)
|
def linear_recur(n)
|
||||||
puts "Рекурсия n = #{n}"
|
puts "Рекурсия n = #{n}"
|
||||||
return if n == 1
|
return if n == 1
|
||||||
@@ -1937,55 +1841,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="space_complexity.rb"
|
```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)
|
def quadratic(n)
|
||||||
# Двумерный список занимает O(n^2) памяти
|
# Двумерный список занимает O(n^2) памяти
|
||||||
Array.new(n) { Array.new(n, 0) }
|
Array.new(n) { Array.new(n, 0) }
|
||||||
@@ -2163,61 +2019,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="space_complexity.rb"
|
```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)
|
def quadratic_recur(n)
|
||||||
return 0 unless n > 0
|
return 0 unless n > 0
|
||||||
|
|
||||||
@@ -2410,70 +2212,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="space_complexity.rb"
|
```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)
|
def build_tree(n)
|
||||||
return if n == 0
|
return if n == 0
|
||||||
|
|
||||||
|
|||||||
@@ -1182,13 +1182,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def constant(n)
|
||||||
count = 0
|
count = 0
|
||||||
size = 100000
|
size = 100000
|
||||||
@@ -1357,23 +1351,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def linear(n)
|
||||||
count = 0
|
count = 0
|
||||||
(0...n).each { count += 1 }
|
(0...n).each { count += 1 }
|
||||||
@@ -1557,30 +1535,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def array_traversal(nums)
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
@@ -1796,42 +1751,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def quadratic(n)
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
@@ -2133,56 +2053,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def bubble_sort(nums)
|
||||||
count = 0 # Счетчик
|
count = 0 # Счетчик
|
||||||
|
|
||||||
@@ -2438,77 +2309,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def exponential(n)
|
||||||
count, base = 0, 1
|
count, base = 0, 1
|
||||||
|
|
||||||
@@ -2668,91 +2469,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def exp_recur(n)
|
||||||
return 1 if n == 1
|
return 1 if n == 1
|
||||||
exp_recur(n - 1) + exp_recur(n - 1) + 1
|
exp_recur(n - 1) + exp_recur(n - 1) + 1
|
||||||
@@ -2943,97 +2660,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def logarithmic(n)
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
@@ -3190,109 +2817,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def log_recur(n)
|
||||||
return 0 unless n > 1
|
return 0 unless n > 1
|
||||||
log_recur(n / 2) + 1
|
log_recur(n / 2) + 1
|
||||||
@@ -3502,115 +3027,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def linear_log_recur(n)
|
||||||
return 1 unless n > 1
|
return 1 unless n > 1
|
||||||
|
|
||||||
@@ -3835,125 +3252,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="time_complexity.rb"
|
```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)
|
def factorial_recur(n)
|
||||||
return 1 if n == 0
|
return 1 if n == 0
|
||||||
|
|
||||||
@@ -4339,13 +3638,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="worst_best_time_complexity.rb"
|
```ruby title="worst_best_time_complexity.rb"
|
||||||
=begin
|
### Создать массив с элементами: 1, 2, ..., n в случайном порядке ###
|
||||||
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)
|
def random_numbers(n)
|
||||||
# Создать массив nums =: 1, 2, 3, ..., n
|
# Создать массив nums =: 1, 2, 3, ..., n
|
||||||
nums = Array.new(n) { |i| i + 1 }
|
nums = Array.new(n) { |i| i + 1 }
|
||||||
@@ -4353,21 +3646,7 @@ $$
|
|||||||
nums.shuffle!
|
nums.shuffle!
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Найти индекс числа 1 в массиве nums ###
|
||||||
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 ###
|
|
||||||
def find_one(nums)
|
def find_one(nums)
|
||||||
for i in 0...nums.length
|
for i in 0...nums.length
|
||||||
# Когда элемент 1 находится в начале массива, достигается лучшая временная сложность O(1)
|
# Когда элемент 1 находится в начале массива, достигается лучшая временная сложность O(1)
|
||||||
|
|||||||
@@ -422,13 +422,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search_recur.rb"
|
```ruby title="binary_search_recur.rb"
|
||||||
=begin
|
### Бинарный поиск: задача f(i, j) ###
|
||||||
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)
|
def dfs(nums, target, i, j)
|
||||||
# Если интервал пуст, целевой элемент отсутствует, вернуть -1
|
# Если интервал пуст, целевой элемент отсутствует, вернуть -1
|
||||||
return -1 if i > j
|
return -1 if i > j
|
||||||
@@ -448,33 +442,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
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)
|
def binary_search(nums, target)
|
||||||
n = nums.length
|
n = nums.length
|
||||||
# Решить задачу f(0, n-1)
|
# Решить задачу f(0, n-1)
|
||||||
|
|||||||
@@ -485,16 +485,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="build_tree.rb"
|
```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)
|
def dfs(preorder, inorder_map, i, l, r)
|
||||||
# Завершить при пустом диапазоне поддерева
|
# Завершить при пустом диапазоне поддерева
|
||||||
return if r - l < 0
|
return if r - l < 0
|
||||||
@@ -512,34 +503,7 @@ comments: true
|
|||||||
root
|
root
|
||||||
end
|
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)
|
def build_tree(preorder, inorder)
|
||||||
# Инициализировать хеш-таблицу для хранения соответствия элементов inorder их индексам
|
# Инициализировать хеш-таблицу для хранения соответствия элементов inorder их индексам
|
||||||
inorder_map = {}
|
inorder_map = {}
|
||||||
|
|||||||
@@ -510,13 +510,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="hanota.rb"
|
```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)
|
def move(src, tar)
|
||||||
# Снять диск с вершины src
|
# Снять диск с вершины src
|
||||||
pan = src.pop
|
pan = src.pop
|
||||||
@@ -524,21 +518,7 @@ comments: true
|
|||||||
tar << pan
|
tar << pan
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Решить задачу Ханойской башни f(i) ###
|
||||||
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)
|
def dfs(i, src, buf, tar)
|
||||||
# Если в src остался только один диск, сразу переместить его в tar
|
# Если в src остался только один диск, сразу переместить его в tar
|
||||||
if i == 1
|
if i == 1
|
||||||
@@ -554,37 +534,7 @@ comments: true
|
|||||||
dfs(i - 1, buf, src, tar)
|
dfs(i - 1, buf, src, tar)
|
||||||
end
|
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)
|
def solve_hanota(_A, _B, _C)
|
||||||
n = _A.length
|
n = _A.length
|
||||||
# Переместить верхние n дисков из A в C с помощью B
|
# Переместить верхние n дисков из A в C с помощью B
|
||||||
|
|||||||
@@ -304,13 +304,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="min_cost_climbing_stairs_dp.rb"
|
```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)
|
def min_cost_climbing_stairs_dp(cost)
|
||||||
n = cost.length - 1
|
n = cost.length - 1
|
||||||
return cost[n] if n == 1 || n == 2
|
return cost[n] if n == 1 || n == 2
|
||||||
@@ -564,13 +558,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="min_cost_climbing_stairs_dp.rb"
|
```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)
|
def min_cost_climbing_stairs_dp(cost)
|
||||||
n = cost.length - 1
|
n = cost.length - 1
|
||||||
return cost[n] if n == 1 || n == 2
|
return cost[n] if n == 1 || n == 2
|
||||||
@@ -935,13 +923,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="climbing_stairs_constraint_dp.rb"
|
```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)
|
def climbing_stairs_constraint_dp(n)
|
||||||
return 1 if n == 1 || n == 2
|
return 1 if n == 1 || n == 2
|
||||||
|
|
||||||
|
|||||||
@@ -369,13 +369,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="min_path_sum.rb"
|
```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)
|
def min_path_sum_dfs(grid, i, j)
|
||||||
# Если это верхняя левая ячейка, завершить поиск
|
# Если это верхняя левая ячейка, завершить поиск
|
||||||
return grid[i][j] if i == 0 && j == 0
|
return grid[i][j] if i == 0 && j == 0
|
||||||
@@ -732,26 +726,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="min_path_sum.rb"
|
```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)
|
def min_path_sum_dfs_mem(grid, mem, i, j)
|
||||||
# Если это верхняя левая ячейка, завершить поиск
|
# Если это верхняя левая ячейка, завершить поиск
|
||||||
return grid[0][0] if i == 0 && j == 0
|
return grid[0][0] if i == 0 && j == 0
|
||||||
@@ -1122,41 +1097,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="min_path_sum.rb"
|
```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)
|
def min_path_sum_dp(grid)
|
||||||
n, m = grid.length, grid.first.length
|
n, m = grid.length, grid.first.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
@@ -1545,60 +1486,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="min_path_sum.rb"
|
```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)
|
def min_path_sum_dp_comp(grid)
|
||||||
n, m = grid.length, grid.first.length
|
n, m = grid.length, grid.first.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
|
|||||||
@@ -454,50 +454,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="edit_distance.rb"
|
```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)
|
def edit_distance_dp(s, t)
|
||||||
n, m = s.length, t.length
|
n, m = s.length, t.length
|
||||||
dp = Array.new(n + 1) { Array.new(m + 1, 0) }
|
dp = Array.new(n + 1) { Array.new(m + 1, 0) }
|
||||||
@@ -981,72 +938,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="edit_distance.rb"
|
```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)
|
def edit_distance_dp_comp(s, t)
|
||||||
n, m = s.length, t.length
|
n, m = s.length, t.length
|
||||||
dp = Array.new(m + 1, 0)
|
dp = Array.new(m + 1, 0)
|
||||||
|
|||||||
@@ -395,13 +395,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="climbing_stairs_backtrack.rb"
|
```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)
|
def backtrack(choices, state, n, res)
|
||||||
# Когда подъем достигает n-й ступени, число вариантов увеличивается на 1
|
# Когда подъем достигает n-й ступени, число вариантов увеличивается на 1
|
||||||
res[0] += 1 if state == n
|
res[0] += 1 if state == n
|
||||||
@@ -416,28 +410,7 @@ comments: true
|
|||||||
# Откат
|
# Откат
|
||||||
end
|
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)
|
def climbing_stairs_backtrack(n)
|
||||||
choices = [1, 2] # Можно подняться на 1 или 2 ступени
|
choices = [1, 2] # Можно подняться на 1 или 2 ступени
|
||||||
state = 0 # Начать подъем с 0-й ступени
|
state = 0 # Начать подъем с 0-й ступени
|
||||||
@@ -708,13 +681,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="climbing_stairs_dfs.rb"
|
```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)
|
def dfs(i)
|
||||||
# dp[1] и dp[2] уже известны, вернуть их
|
# dp[1] и dp[2] уже известны, вернуть их
|
||||||
return i if i == 1 || i == 2
|
return i if i == 1 || i == 2
|
||||||
@@ -722,21 +689,7 @@ $$
|
|||||||
dfs(i - 1) + dfs(i - 2)
|
dfs(i - 1) + dfs(i - 2)
|
||||||
end
|
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)
|
def climbing_stairs_dfs(n)
|
||||||
dfs(n)
|
dfs(n)
|
||||||
end
|
end
|
||||||
@@ -1088,13 +1041,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="climbing_stairs_dfs_mem.rb"
|
```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)
|
def dfs(i, mem)
|
||||||
# dp[1] и dp[2] уже известны, вернуть их
|
# dp[1] и dp[2] уже известны, вернуть их
|
||||||
return i if i == 1 || i == 2
|
return i if i == 1 || i == 2
|
||||||
@@ -1107,26 +1054,7 @@ $$
|
|||||||
mem[i] = count
|
mem[i] = count
|
||||||
end
|
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)
|
def climbing_stairs_dfs_mem(n)
|
||||||
# mem[i] хранит число способов подняться на i-ю ступень, -1 означает отсутствие записи
|
# mem[i] хранит число способов подняться на i-ю ступень, -1 означает отсутствие записи
|
||||||
mem = Array.new(n + 1, -1)
|
mem = Array.new(n + 1, -1)
|
||||||
@@ -1395,13 +1323,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="climbing_stairs_dp.rb"
|
```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)
|
def climbing_stairs_dp(n)
|
||||||
return n if n == 1 || n == 2
|
return n if n == 1 || n == 2
|
||||||
|
|
||||||
@@ -1642,27 +1564,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="climbing_stairs_dp.rb"
|
```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)
|
def climbing_stairs_dp_comp(n)
|
||||||
return n if n == 1 || n == 2
|
return n if n == 1 || n == 2
|
||||||
|
|
||||||
|
|||||||
@@ -324,13 +324,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="knapsack.rb"
|
```ruby title="knapsack.rb"
|
||||||
=begin
|
### Рюкзак 0-1: полный перебор ###
|
||||||
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)
|
def knapsack_dfs(wgt, val, i, c)
|
||||||
# Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0
|
# Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0
|
||||||
return 0 if i == 0 || c == 0
|
return 0 if i == 0 || c == 0
|
||||||
@@ -696,26 +690,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="knapsack.rb"
|
```ruby title="knapsack.rb"
|
||||||
=begin
|
### Рюкзак 0-1: поиск с мемоизацией ###
|
||||||
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)
|
def knapsack_dfs_mem(wgt, val, mem, i, c)
|
||||||
# Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0
|
# Если все предметы уже рассмотрены или в рюкзаке не осталось места, вернуть стоимость 0
|
||||||
return 0 if i == 0 || c == 0
|
return 0 if i == 0 || c == 0
|
||||||
@@ -1061,41 +1036,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="knapsack.rb"
|
```ruby title="knapsack.rb"
|
||||||
=begin
|
### Рюкзак 0-1: динамическое программирование ###
|
||||||
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)
|
def knapsack_dp(wgt, val, cap)
|
||||||
n = wgt.length
|
n = wgt.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
@@ -1476,61 +1417,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="knapsack.rb"
|
```ruby title="knapsack.rb"
|
||||||
=begin
|
### Рюкзак 0-1: динамическое программирование с оптимизацией памяти ###
|
||||||
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: динамическое программирование с оптимизацией памяти ###
|
|
||||||
def knapsack_dp_comp(wgt, val, cap)
|
def knapsack_dp_comp(wgt, val, cap)
|
||||||
n = wgt.length
|
n = wgt.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
|
|||||||
@@ -350,13 +350,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="unbounded_knapsack.rb"
|
```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)
|
def unbounded_knapsack_dp(wgt, val, cap)
|
||||||
n = wgt.length
|
n = wgt.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
@@ -709,13 +703,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="unbounded_knapsack.rb"
|
```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)
|
def unbounded_knapsack_dp(wgt, val, cap)
|
||||||
n = wgt.length
|
n = wgt.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
@@ -735,7 +723,7 @@ $$
|
|||||||
dp[n][cap]
|
dp[n][cap]
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Полный рюкзак: динамическое программирование с оптимизацией памяти ##3
|
### Полный рюкзак: динамическое программирование с оптимизацией памяти ##3
|
||||||
def unbounded_knapsack_dp_comp(wgt, val, cap)
|
def unbounded_knapsack_dp_comp(wgt, val, cap)
|
||||||
n = wgt.length
|
n = wgt.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
@@ -1180,13 +1168,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="coin_change.rb"
|
```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)
|
def coin_change_dp(coins, amt)
|
||||||
n = coins.length
|
n = coins.length
|
||||||
_MAX = amt + 1
|
_MAX = amt + 1
|
||||||
@@ -1601,36 +1583,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="coin_change.rb"
|
```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)
|
def coin_change_dp_comp(coins, amt)
|
||||||
n = coins.length
|
n = coins.length
|
||||||
_MAX = amt + 1
|
_MAX = amt + 1
|
||||||
@@ -2033,13 +1986,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="coin_change_ii.rb"
|
```ruby title="coin_change_ii.rb"
|
||||||
=begin
|
### Размен монет II: динамическое программирование ###
|
||||||
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)
|
def coin_change_ii_dp(coins, amt)
|
||||||
n = coins.length
|
n = coins.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
@@ -2375,35 +2322,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="coin_change_ii.rb"
|
```ruby title="coin_change_ii.rb"
|
||||||
=begin
|
### Размен монет II: динамическое программирование с оптимизацией памяти ###
|
||||||
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: динамическое программирование с оптимизацией памяти ###
|
|
||||||
def coin_change_ii_dp_comp(coins, amt)
|
def coin_change_ii_dp_comp(coins, amt)
|
||||||
n = coins.length
|
n = coins.length
|
||||||
# Инициализация таблицы dp
|
# Инициализация таблицы dp
|
||||||
|
|||||||
@@ -1130,18 +1130,10 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="graph_adjacency_matrix.rb"
|
```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
|
class GraphAdjMat
|
||||||
def initialize(vertices, edges)
|
def initialize(vertices, edges)
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
# Список вершин: элементы представляют «значения вершин», а индексы — «индексы вершин»
|
# Список вершин: элементы представляют «значения вершин», а индексы — «индексы вершин»
|
||||||
@vertices = []
|
@vertices = []
|
||||||
# Матрица смежности, где индексы строк и столбцов соответствуют «индексам вершин»
|
# Матрица смежности, где индексы строк и столбцов соответствуют «индексам вершин»
|
||||||
@@ -1153,12 +1145,12 @@ comments: true
|
|||||||
edges.each { |e| add_edge(e[0], e[1]) }
|
edges.each { |e| add_edge(e[0], e[1]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получение числа вершин ###
|
### Получение числа вершин ###
|
||||||
def size
|
def size
|
||||||
@vertices.length
|
@vertices.length
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление вершины ###
|
### Добавление вершины ###
|
||||||
def add_vertex(val)
|
def add_vertex(val)
|
||||||
n = size
|
n = size
|
||||||
# Добавить значение новой вершины в список вершин
|
# Добавить значение новой вершины в список вершин
|
||||||
@@ -1170,7 +1162,7 @@ comments: true
|
|||||||
@adj_mat.each { |row| row << 0 }
|
@adj_mat.each { |row| row << 0 }
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Удаление вершины ###
|
### Удаление вершины ###
|
||||||
def remove_vertex(index)
|
def remove_vertex(index)
|
||||||
raise IndexError if index >= size
|
raise IndexError if index >= size
|
||||||
|
|
||||||
@@ -1182,7 +1174,7 @@ comments: true
|
|||||||
@adj_mat.each { |row| row.delete_at(index) }
|
@adj_mat.each { |row| row.delete_at(index) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление ребра ###
|
### Добавление ребра ###
|
||||||
def add_edge(i, j)
|
def add_edge(i, j)
|
||||||
# Параметры i и j соответствуют индексам элементов vertices
|
# Параметры i и j соответствуют индексам элементов vertices
|
||||||
# Обработка выхода индекса за границы и случая равенства
|
# Обработка выхода индекса за границы и случая равенства
|
||||||
@@ -1194,7 +1186,7 @@ comments: true
|
|||||||
@adj_mat[j][i] = 1
|
@adj_mat[j][i] = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Удаление ребра ###
|
### Удаление ребра ###
|
||||||
def remove_edge(i, j)
|
def remove_edge(i, j)
|
||||||
# Параметры i и j соответствуют индексам элементов vertices
|
# Параметры i и j соответствуют индексам элементов vertices
|
||||||
# Обработка выхода индекса за границы и случая равенства
|
# Обработка выхода индекса за границы и случая равенства
|
||||||
@@ -1205,7 +1197,7 @@ comments: true
|
|||||||
@adj_mat[j][i] = 0
|
@adj_mat[j][i] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вывести матрицу смежности ###
|
### Вывести матрицу смежности ###
|
||||||
def __print__
|
def __print__
|
||||||
puts "Список вершин = #{@vertices}"
|
puts "Список вершин = #{@vertices}"
|
||||||
puts 'Матрица смежности ='
|
puts 'Матрица смежности ='
|
||||||
@@ -2303,19 +2295,11 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="graph_adjacency_list.rb"
|
```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
|
class GraphAdjList
|
||||||
attr_reader :adj_list
|
attr_reader :adj_list
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize(edges)
|
def initialize(edges)
|
||||||
# Список смежности, где key — вершина, а value — все смежные ей вершины
|
# Список смежности, где key — вершина, а value — все смежные ей вершины
|
||||||
@adj_list = {}
|
@adj_list = {}
|
||||||
@@ -2327,12 +2311,12 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получение числа вершин ###
|
### Получение числа вершин ###
|
||||||
def size
|
def size
|
||||||
@adj_list.length
|
@adj_list.length
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление ребра ###
|
### Добавление ребра ###
|
||||||
def add_edge(vet1, vet2)
|
def add_edge(vet1, vet2)
|
||||||
raise ArgumentError if !@adj_list.include?(vet1) || !@adj_list.include?(vet2)
|
raise ArgumentError if !@adj_list.include?(vet1) || !@adj_list.include?(vet2)
|
||||||
|
|
||||||
@@ -2340,7 +2324,7 @@ comments: true
|
|||||||
@adj_list[vet2] << vet1
|
@adj_list[vet2] << vet1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Удаление ребра ###
|
### Удаление ребра ###
|
||||||
def remove_edge(vet1, vet2)
|
def remove_edge(vet1, vet2)
|
||||||
raise ArgumentError if !@adj_list.include?(vet1) || !@adj_list.include?(vet2)
|
raise ArgumentError if !@adj_list.include?(vet1) || !@adj_list.include?(vet2)
|
||||||
|
|
||||||
@@ -2349,7 +2333,7 @@ comments: true
|
|||||||
@adj_list[vet2].delete(vet1)
|
@adj_list[vet2].delete(vet1)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление вершины ###
|
### Добавление вершины ###
|
||||||
def add_vertex(vet)
|
def add_vertex(vet)
|
||||||
return if @adj_list.include?(vet)
|
return if @adj_list.include?(vet)
|
||||||
|
|
||||||
@@ -2357,7 +2341,7 @@ comments: true
|
|||||||
@adj_list[vet] = []
|
@adj_list[vet] = []
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Удаление вершины ###
|
### Удаление вершины ###
|
||||||
def remove_vertex(vet)
|
def remove_vertex(vet)
|
||||||
raise ArgumentError unless @adj_list.include?(vet)
|
raise ArgumentError unless @adj_list.include?(vet)
|
||||||
|
|
||||||
@@ -2369,7 +2353,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вывести список смежности ###
|
### Вывести список смежности ###
|
||||||
def __print__
|
def __print__
|
||||||
puts 'Список смежности ='
|
puts 'Список смежности ='
|
||||||
for vertex in @adj_list
|
for vertex in @adj_list
|
||||||
|
|||||||
@@ -450,17 +450,7 @@ BFS обычно реализуется с помощью очереди, код
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="graph_bfs.rb"
|
```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)
|
def graph_bfs(graph, start_vet)
|
||||||
# Использовать список смежности для представления графа, чтобы получать все смежные вершины заданной вершины
|
# Использовать список смежности для представления графа, чтобы получать все смежные вершины заданной вершины
|
||||||
# Последовательность обхода вершин
|
# Последовательность обхода вершин
|
||||||
@@ -921,17 +911,7 @@ BFS обычно реализуется с помощью очереди, код
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="graph_dfs.rb"
|
```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)
|
def dfs(graph, visited, res, vet)
|
||||||
res << vet # Отметить посещенную вершину
|
res << vet # Отметить посещенную вершину
|
||||||
visited.add(vet) # Отметить эту вершину как посещенную
|
visited.add(vet) # Отметить эту вершину как посещенную
|
||||||
@@ -943,29 +923,7 @@ BFS обычно реализуется с помощью очереди, код
|
|||||||
end
|
end
|
||||||
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)
|
def graph_dfs(graph, start_vet)
|
||||||
# Использовать список смежности для представления графа, чтобы получать все смежные вершины заданной вершины
|
# Использовать список смежности для представления графа, чтобы получать все смежные вершины заданной вершины
|
||||||
# Последовательность обхода вершин
|
# Последовательность обхода вершин
|
||||||
|
|||||||
@@ -496,13 +496,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="fractional_knapsack.rb"
|
```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
|
class Item
|
||||||
attr_accessor :w # Вес предмета
|
attr_accessor :w # Вес предмета
|
||||||
attr_accessor :v # Стоимость предмета
|
attr_accessor :v # Стоимость предмета
|
||||||
@@ -513,24 +507,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
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)
|
def fractional_knapsack(wgt, val, cap)
|
||||||
# Создать список предметов с двумя свойствами: вес и стоимость
|
# Создать список предметов с двумя свойствами: вес и стоимость
|
||||||
items = wgt.each_with_index.map { |w, i| Item.new(w, val[i]) }
|
items = wgt.each_with_index.map { |w, i| Item.new(w, val[i]) }
|
||||||
|
|||||||
@@ -310,13 +310,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="coin_change_greedy.rb"
|
```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)
|
def coin_change_greedy(coins, amt)
|
||||||
# Предположить, что список coins упорядочен
|
# Предположить, что список coins упорядочен
|
||||||
i = coins.length - 1
|
i = coins.length - 1
|
||||||
|
|||||||
@@ -397,13 +397,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="max_capacity.rb"
|
```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)
|
def max_capacity(ht)
|
||||||
# Инициализировать i и j так, чтобы они располагались по двум концам массива
|
# Инициализировать i и j так, чтобы они располагались по двум концам массива
|
||||||
i, j = 0, ht.length - 1
|
i, j = 0, ht.length - 1
|
||||||
|
|||||||
@@ -371,13 +371,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="max_product_cutting.rb"
|
```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)
|
def max_product_cutting(n)
|
||||||
# Когда n <= 3, обязательно нужно выделить одну 1
|
# Когда n <= 3, обязательно нужно выделить одну 1
|
||||||
return 1 * (n - 1) if n <= 3
|
return 1 * (n - 1) if n <= 3
|
||||||
|
|||||||
@@ -601,13 +601,7 @@ index = hash(key) % capacity
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="simple_hash.rb"
|
```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)
|
def add_hash(key)
|
||||||
hash = 0
|
hash = 0
|
||||||
modulus = 1_000_000_007
|
modulus = 1_000_000_007
|
||||||
@@ -617,23 +611,7 @@ index = hash(key) % capacity
|
|||||||
hash % modulus
|
hash % modulus
|
||||||
end
|
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)
|
def mul_hash(key)
|
||||||
hash = 0
|
hash = 0
|
||||||
modulus = 1_000_000_007
|
modulus = 1_000_000_007
|
||||||
@@ -643,33 +621,7 @@ index = hash(key) % capacity
|
|||||||
hash % modulus
|
hash % modulus
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### XOR-хеширование ###
|
||||||
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)
|
def xor_hash(key)
|
||||||
hash = 0
|
hash = 0
|
||||||
modulus = 1_000_000_007
|
modulus = 1_000_000_007
|
||||||
@@ -679,43 +631,7 @@ index = hash(key) % capacity
|
|||||||
hash % modulus
|
hash % modulus
|
||||||
end
|
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)
|
def rot_hash(key)
|
||||||
hash = 0
|
hash = 0
|
||||||
modulus = 1_000_000_007
|
modulus = 1_000_000_007
|
||||||
|
|||||||
@@ -1422,17 +1422,9 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="hash_map_chaining.rb"
|
```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
|
class HashMapChaining
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize
|
def initialize
|
||||||
@size = 0 # Число пар ключ-значение
|
@size = 0 # Число пар ключ-значение
|
||||||
@capacity = 4 # Вместимость хеш-таблицы
|
@capacity = 4 # Вместимость хеш-таблицы
|
||||||
@@ -1441,17 +1433,17 @@ comments: true
|
|||||||
@buckets = Array.new(@capacity) { [] } # Массив корзин
|
@buckets = Array.new(@capacity) { [] } # Массив корзин
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Хеш-функция ###
|
### Хеш-функция ###
|
||||||
def hash_func(key)
|
def hash_func(key)
|
||||||
key % @capacity
|
key % @capacity
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Коэффициент загрузки ###
|
### Коэффициент загрузки ###
|
||||||
def load_factor
|
def load_factor
|
||||||
@size / @capacity
|
@size / @capacity
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция поиска ###
|
### Операция поиска ###
|
||||||
def get(key)
|
def get(key)
|
||||||
index = hash_func(key)
|
index = hash_func(key)
|
||||||
bucket = @buckets[index]
|
bucket = @buckets[index]
|
||||||
@@ -1463,7 +1455,7 @@ comments: true
|
|||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция добавления ###
|
### Операция добавления ###
|
||||||
def put(key, val)
|
def put(key, val)
|
||||||
# Когда коэффициент загрузки превышает порог, выполнить расширение
|
# Когда коэффициент загрузки превышает порог, выполнить расширение
|
||||||
extend if load_factor > @load_thres
|
extend if load_factor > @load_thres
|
||||||
@@ -1482,7 +1474,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция удаления ###
|
### Операция удаления ###
|
||||||
def remove(key)
|
def remove(key)
|
||||||
index = hash_func(key)
|
index = hash_func(key)
|
||||||
bucket = @buckets[index]
|
bucket = @buckets[index]
|
||||||
@@ -1496,7 +1488,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Расширение хеш-таблицы ###
|
### Расширение хеш-таблицы ###
|
||||||
def extend
|
def extend
|
||||||
# Временно сохранить исходную хеш-таблицу
|
# Временно сохранить исходную хеш-таблицу
|
||||||
buckets = @buckets
|
buckets = @buckets
|
||||||
@@ -1512,7 +1504,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вывести хеш-таблицу ###
|
### Вывести хеш-таблицу ###
|
||||||
def print
|
def print
|
||||||
for bucket in @buckets
|
for bucket in @buckets
|
||||||
res = []
|
res = []
|
||||||
@@ -3176,19 +3168,11 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="hash_map_open_addressing.rb"
|
```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
|
class HashMapOpenAddressing
|
||||||
TOMBSTONE = Pair.new(-1, '-1') # Удалить метку
|
TOMBSTONE = Pair.new(-1, '-1') # Удалить метку
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize
|
def initialize
|
||||||
@size = 0 # Число пар ключ-значение
|
@size = 0 # Число пар ключ-значение
|
||||||
@capacity = 4 # Вместимость хеш-таблицы
|
@capacity = 4 # Вместимость хеш-таблицы
|
||||||
@@ -3197,17 +3181,17 @@ comments: true
|
|||||||
@buckets = Array.new(@capacity) # Массив корзин
|
@buckets = Array.new(@capacity) # Массив корзин
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Хеш-функция ###
|
### Хеш-функция ###
|
||||||
def hash_func(key)
|
def hash_func(key)
|
||||||
key % @capacity
|
key % @capacity
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Коэффициент загрузки ###
|
### Коэффициент загрузки ###
|
||||||
def load_factor
|
def load_factor
|
||||||
@size / @capacity
|
@size / @capacity
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Найти индекс корзины, соответствующий key ###
|
### Найти индекс корзины, соответствующий key ###
|
||||||
def find_bucket(key)
|
def find_bucket(key)
|
||||||
index = hash_func(key)
|
index = hash_func(key)
|
||||||
first_tombstone = -1
|
first_tombstone = -1
|
||||||
@@ -3232,7 +3216,7 @@ comments: true
|
|||||||
first_tombstone == -1 ? index : first_tombstone
|
first_tombstone == -1 ? index : first_tombstone
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция поиска ###
|
### Операция поиска ###
|
||||||
def get(key)
|
def get(key)
|
||||||
# Найти индекс корзины, соответствующий key
|
# Найти индекс корзины, соответствующий key
|
||||||
index = find_bucket(key)
|
index = find_bucket(key)
|
||||||
@@ -3242,7 +3226,7 @@ comments: true
|
|||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция добавления ###
|
### Операция добавления ###
|
||||||
def put(key, val)
|
def put(key, val)
|
||||||
# Когда коэффициент загрузки превышает порог, выполнить расширение
|
# Когда коэффициент загрузки превышает порог, выполнить расширение
|
||||||
extend if load_factor > @load_thres
|
extend if load_factor > @load_thres
|
||||||
@@ -3258,7 +3242,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция удаления ###
|
### Операция удаления ###
|
||||||
def remove(key)
|
def remove(key)
|
||||||
# Найти индекс корзины, соответствующий key
|
# Найти индекс корзины, соответствующий key
|
||||||
index = find_bucket(key)
|
index = find_bucket(key)
|
||||||
@@ -3269,7 +3253,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Расширение хеш-таблицы ###
|
### Расширение хеш-таблицы ###
|
||||||
def extend
|
def extend
|
||||||
# Временно сохранить исходную хеш-таблицу
|
# Временно сохранить исходную хеш-таблицу
|
||||||
buckets_tmp = @buckets
|
buckets_tmp = @buckets
|
||||||
@@ -3283,7 +3267,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вывести хеш-таблицу ###
|
### Вывести хеш-таблицу ###
|
||||||
def print
|
def print
|
||||||
for pair in @buckets
|
for pair in @buckets
|
||||||
if pair.nil?
|
if pair.nil?
|
||||||
|
|||||||
@@ -1677,13 +1677,7 @@ index = hash(key) % capacity
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array_hash_map.rb"
|
```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
|
class Pair
|
||||||
attr_accessor :key, :val
|
attr_accessor :key, :val
|
||||||
|
|
||||||
@@ -1693,36 +1687,20 @@ index = hash(key) % capacity
|
|||||||
end
|
end
|
||||||
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
|
class ArrayHashMap
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize
|
def initialize
|
||||||
# Инициализировать массив, содержащий 100 корзин
|
# Инициализировать массив, содержащий 100 корзин
|
||||||
@buckets = Array.new(100)
|
@buckets = Array.new(100)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Хеш-функция ###
|
### Хеш-функция ###
|
||||||
def hash_func(key)
|
def hash_func(key)
|
||||||
index = key % 100
|
index = key % 100
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция поиска ###
|
### Операция поиска ###
|
||||||
def get(key)
|
def get(key)
|
||||||
index = hash_func(key)
|
index = hash_func(key)
|
||||||
pair = @buckets[index]
|
pair = @buckets[index]
|
||||||
@@ -1731,42 +1709,42 @@ index = hash(key) % capacity
|
|||||||
pair.val
|
pair.val
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция добавления ###
|
### Операция добавления ###
|
||||||
def put(key, val)
|
def put(key, val)
|
||||||
pair = Pair.new(key, val)
|
pair = Pair.new(key, val)
|
||||||
index = hash_func(key)
|
index = hash_func(key)
|
||||||
@buckets[index] = pair
|
@buckets[index] = pair
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция удаления ###
|
### Операция удаления ###
|
||||||
def remove(key)
|
def remove(key)
|
||||||
index = hash_func(key)
|
index = hash_func(key)
|
||||||
# Присвоить nil, что означает удаление
|
# Присвоить nil, что означает удаление
|
||||||
@buckets[index] = nil
|
@buckets[index] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить все пары ключ-значение ###
|
### Получить все пары ключ-значение ###
|
||||||
def entry_set
|
def entry_set
|
||||||
result = []
|
result = []
|
||||||
@buckets.each { |pair| result << pair unless pair.nil? }
|
@buckets.each { |pair| result << pair unless pair.nil? }
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить все ключи ###
|
### Получить все ключи ###
|
||||||
def key_set
|
def key_set
|
||||||
result = []
|
result = []
|
||||||
@buckets.each { |pair| result << pair.key unless pair.nil? }
|
@buckets.each { |pair| result << pair.key unless pair.nil? }
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить все значения ###
|
### Получить все значения ###
|
||||||
def value_set
|
def value_set
|
||||||
result = []
|
result = []
|
||||||
@buckets.each { |pair| result << pair.val unless pair.nil? }
|
@buckets.each { |pair| result << pair.val unless pair.nil? }
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вывести хеш-таблицу ###
|
### Вывести хеш-таблицу ###
|
||||||
def print
|
def print
|
||||||
@buckets.each { |pair| puts "#{pair.key} -> #{pair.val}" unless pair.nil? }
|
@buckets.each { |pair| puts "#{pair.key} -> #{pair.val}" unless pair.nil? }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -311,19 +311,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="my_heap.rb"
|
```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)
|
def initialize(nums)
|
||||||
# Добавить элементы списка в кучу без изменений
|
# Добавить элементы списка в кучу без изменений
|
||||||
@max_heap = nums
|
@max_heap = nums
|
||||||
|
|||||||
@@ -669,98 +669,17 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="my_heap.rb"
|
```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)
|
def left(i)
|
||||||
2 * i + 1
|
2 * i + 1
|
||||||
end
|
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)
|
def right(i)
|
||||||
2 * i + 2
|
2 * i + 2
|
||||||
end
|
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)
|
def parent(i)
|
||||||
(i - 1) / 2 # Округление вниз при делении
|
(i - 1) / 2 # Округление вниз при делении
|
||||||
end
|
end
|
||||||
@@ -880,59 +799,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="my_heap.rb"
|
```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
|
def peek
|
||||||
@max_heap[0]
|
@max_heap[0]
|
||||||
end
|
end
|
||||||
@@ -1320,64 +1187,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="my_heap.rb"
|
```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)
|
def push(val)
|
||||||
# Добавление узла
|
# Добавление узла
|
||||||
@max_heap << val
|
@max_heap << val
|
||||||
@@ -1385,72 +1195,7 @@ comments: true
|
|||||||
sift_up(size - 1)
|
sift_up(size - 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Начиная с узла i, выполнить просеивание снизу вверх ###
|
||||||
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)
|
def sift_up(i)
|
||||||
loop do
|
loop do
|
||||||
# Получение родительского узла для узла i
|
# Получение родительского узла для узла i
|
||||||
@@ -1989,86 +1734,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="my_heap.rb"
|
```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
|
def pop
|
||||||
# Обработка пустого случая
|
# Обработка пустого случая
|
||||||
raise IndexError, "куча пуста" if is_empty?
|
raise IndexError, "куча пуста" if is_empty?
|
||||||
@@ -2082,100 +1748,7 @@ comments: true
|
|||||||
val
|
val
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Начиная с узла i, выполнить просеивание сверху вниз ###
|
||||||
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, выполнить просеивание сверху вниз ###
|
|
||||||
def sift_down(i)
|
def sift_down(i)
|
||||||
loop do
|
loop do
|
||||||
# Определить узел с максимальным значением среди i, l и r и обозначить его как ma
|
# Определить узел с максимальным значением среди i, l и r и обозначить его как ma
|
||||||
|
|||||||
@@ -437,39 +437,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="top_k.rb"
|
```ruby title="top_k.rb"
|
||||||
=begin
|
### Поиск k наибольших элементов массива с помощью кучи ###
|
||||||
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 наибольших элементов массива с помощью кучи ###
|
|
||||||
def top_k_heap(nums, k)
|
def top_k_heap(nums, k)
|
||||||
# Инициализация минимальной кучи
|
# Инициализация минимальной кучи
|
||||||
# Обратите внимание: мы инвертируем все элементы кучи, чтобы с помощью максимальной кучи имитировать минимальную
|
# Обратите внимание: мы инвертируем все элементы кучи, чтобы с помощью максимальной кучи имитировать минимальную
|
||||||
|
|||||||
@@ -339,13 +339,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search.rb"
|
```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)
|
def binary_search(nums, target)
|
||||||
# Инициализировать двусторонне замкнутый интервал [0, n-1], то есть i и j указывают на первый и последний элементы массива соответственно
|
# Инициализировать двусторонне замкнутый интервал [0, n-1], то есть i и j указывают на первый и последний элементы массива соответственно
|
||||||
i, j = 0, nums.length - 1
|
i, j = 0, nums.length - 1
|
||||||
@@ -669,35 +663,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search.rb"
|
```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)
|
def binary_search_lcro(nums, target)
|
||||||
# Инициализировать лево замкнутый, право открытый интервал [0, n), то есть i и j указывают на первый элемент массива и позицию сразу за последним элементом соответственно
|
# Инициализировать лево замкнутый, право открытый интервал [0, n), то есть i и j указывают на первый элемент массива и позицию сразу за последним элементом соответственно
|
||||||
i, j = 0, nums.length
|
i, j = 0, nums.length
|
||||||
|
|||||||
@@ -212,15 +212,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search_edge.rb"
|
```ruby title="binary_search_edge.rb"
|
||||||
=begin
|
### Бинарный поиск самого левого target ###
|
||||||
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)
|
def binary_search_left_edge(nums, target)
|
||||||
# Эквивалентно поиску точки вставки target
|
# Эквивалентно поиску точки вставки target
|
||||||
i = binary_search_insertion(nums, target)
|
i = binary_search_insertion(nums, target)
|
||||||
@@ -472,26 +464,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search_edge.rb"
|
```ruby title="binary_search_edge.rb"
|
||||||
=begin
|
### Бинарный поиск самого правого target ###
|
||||||
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 ###
|
|
||||||
def binary_search_right_edge(nums, target)
|
def binary_search_right_edge(nums, target)
|
||||||
# Преобразовать задачу в поиск самого левого target + 1
|
# Преобразовать задачу в поиск самого левого target + 1
|
||||||
i = binary_search_insertion(nums, target + 1)
|
i = binary_search_insertion(nums, target + 1)
|
||||||
|
|||||||
@@ -293,13 +293,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search_insertion.rb"
|
```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)
|
def binary_search_insertion_simple(nums, target)
|
||||||
# Инициализировать двусторонне замкнутый интервал [0, n-1]
|
# Инициализировать двусторонне замкнутый интервал [0, n-1]
|
||||||
i, j = 0, nums.length - 1
|
i, j = 0, nums.length - 1
|
||||||
@@ -644,34 +638,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search_insertion.rb"
|
```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)
|
def binary_search_insertion(nums, target)
|
||||||
# Инициализировать двусторонне замкнутый интервал [0, n-1]
|
# Инициализировать двусторонне замкнутый интервал [0, n-1]
|
||||||
i, j = 0, nums.length - 1
|
i, j = 0, nums.length - 1
|
||||||
|
|||||||
@@ -228,13 +228,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="two_sum.rb"
|
```ruby title="two_sum.rb"
|
||||||
=begin
|
### Метод 1: полный перебор ###
|
||||||
File: two_sum.rb
|
|
||||||
Created Time: 2024-04-09
|
|
||||||
Author: Blue Bean (lonnnnnnner@gmail.com)
|
|
||||||
=end
|
|
||||||
|
|
||||||
# ## Метод 1: полный перебор ###
|
|
||||||
def two_sum_brute_force(nums, target)
|
def two_sum_brute_force(nums, target)
|
||||||
# Два вложенных цикла, временная сложность O(n^2)
|
# Два вложенных цикла, временная сложность O(n^2)
|
||||||
for i in 0...(nums.length - 1)
|
for i in 0...(nums.length - 1)
|
||||||
@@ -527,25 +521,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="two_sum.rb"
|
```ruby title="two_sum.rb"
|
||||||
=begin
|
### Метод 2: вспомогательная хеш-таблица ###
|
||||||
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: вспомогательная хеш-таблица ###
|
|
||||||
def two_sum_hash_table(nums, target)
|
def two_sum_hash_table(nums, target)
|
||||||
# Вспомогательная хеш-таблица, пространственная сложность O(n)
|
# Вспомогательная хеш-таблица, пространственная сложность O(n)
|
||||||
dic = {}
|
dic = {}
|
||||||
|
|||||||
@@ -274,13 +274,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="bubble_sort.rb"
|
```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)
|
def bubble_sort(nums)
|
||||||
n = nums.length
|
n = nums.length
|
||||||
# Внешний цикл: неотсортированный диапазон [0, i]
|
# Внешний цикл: неотсортированный диапазон [0, i]
|
||||||
@@ -580,28 +574,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="bubble_sort.rb"
|
```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)
|
def bubble_sort_with_flag(nums)
|
||||||
n = nums.length
|
n = nums.length
|
||||||
# Внешний цикл: неотсортированный диапазон [0, i]
|
# Внешний цикл: неотсортированный диапазон [0, i]
|
||||||
|
|||||||
@@ -406,13 +406,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="bucket_sort.rb"
|
```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)
|
def bucket_sort(nums)
|
||||||
# Инициализировать k = n/2 корзин, предполагая распределение 2 элементов в каждую корзину
|
# Инициализировать k = n/2 корзин, предполагая распределение 2 элементов в каждую корзину
|
||||||
k = nums.length / 2
|
k = nums.length / 2
|
||||||
|
|||||||
@@ -340,13 +340,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="counting_sort.rb"
|
```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)
|
def counting_sort_naive(nums)
|
||||||
# Простая реализация, не подходит для сортировки объектов
|
# Простая реализация, не подходит для сортировки объектов
|
||||||
# 1. Найти максимальный элемент массива m
|
# 1. Найти максимальный элемент массива m
|
||||||
@@ -857,33 +851,7 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="counting_sort.rb"
|
```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)
|
def counting_sort(nums)
|
||||||
# Полная реализация, позволяет сортировать объекты и является стабильной сортировкой
|
# Полная реализация, позволяет сортировать объекты и является стабильной сортировкой
|
||||||
# 1. Найти максимальный элемент массива m
|
# 1. Найти максимальный элемент массива m
|
||||||
|
|||||||
@@ -578,13 +578,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="heap_sort.rb"
|
```ruby title="heap_sort.rb"
|
||||||
=begin
|
### Длина кучи равна n; начиная с узла i, выполнить просеивание сверху вниз ###
|
||||||
File: heap_sort.rb
|
|
||||||
Created Time: 2024-04-10
|
|
||||||
Author: junminhong (junminhong1110@gmail.com)
|
|
||||||
=end
|
|
||||||
|
|
||||||
# ## Длина кучи равна n; начиная с узла i, выполнить просеивание сверху вниз ###
|
|
||||||
def sift_down(nums, n, i)
|
def sift_down(nums, n, i)
|
||||||
while true
|
while true
|
||||||
# Определить узел с максимальным значением среди i, l и r и обозначить его как ma
|
# Определить узел с максимальным значением среди i, l и r и обозначить его как ma
|
||||||
@@ -602,31 +596,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
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)
|
def heap_sort(nums)
|
||||||
# Построение кучи: выполнить heapify для всех узлов, кроме листовых
|
# Построение кучи: выполнить heapify для всех узлов, кроме листовых
|
||||||
(nums.length / 2 - 1).downto(0) do |i|
|
(nums.length / 2 - 1).downto(0) do |i|
|
||||||
|
|||||||
@@ -253,13 +253,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="insertion_sort.rb"
|
```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)
|
def insertion_sort(nums)
|
||||||
n = nums.length
|
n = nums.length
|
||||||
# Внешний цикл: отсортированный диапазон [0, i-1]
|
# Внешний цикл: отсортированный диапазон [0, i-1]
|
||||||
|
|||||||
@@ -630,13 +630,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="merge_sort.rb"
|
```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)
|
def merge(nums, left, mid, right)
|
||||||
# Интервал левого подмассива: [left, mid], правого подмассива: [mid+1, right]
|
# Интервал левого подмассива: [left, mid], правого подмассива: [mid+1, right]
|
||||||
# Создать временный массив tmp для хранения результата слияния
|
# Создать временный массив tmp для хранения результата слияния
|
||||||
@@ -671,48 +665,7 @@ comments: true
|
|||||||
end
|
end
|
||||||
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)
|
def merge_sort(nums, left, right)
|
||||||
# Условие завершения
|
# Условие завершения
|
||||||
# Когда длина подмассива равна 1, рекурсия завершается
|
# Когда длина подмассива равна 1, рекурсия завершается
|
||||||
|
|||||||
@@ -346,16 +346,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="quick_sort.rb"
|
```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)
|
def partition(nums, left, right)
|
||||||
# Взять nums[left] в качестве опорного элемента
|
# Взять nums[left] в качестве опорного элемента
|
||||||
i, j = left, right
|
i, j = left, right
|
||||||
@@ -588,35 +579,7 @@ class QuickSort
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="quick_sort.rb"
|
```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)
|
def quick_sort(nums, left, right)
|
||||||
# Рекурсивно обрабатывать, пока длина подмассива не станет равной 1
|
# Рекурсивно обрабатывать, пока длина подмассива не станет равной 1
|
||||||
if left < right
|
if left < right
|
||||||
@@ -1085,53 +1048,7 @@ class QuickSort
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="quick_sort.rb"
|
```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)
|
def median_three(nums, left, mid, right)
|
||||||
# Выбрать медиану из трех кандидатов
|
# Выбрать медиану из трех кандидатов
|
||||||
_l, _m, _r = nums[left], nums[mid], nums[right]
|
_l, _m, _r = nums[left], nums[mid], nums[right]
|
||||||
@@ -1142,66 +1059,9 @@ class QuickSortMedian
|
|||||||
return right
|
return right
|
||||||
end
|
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)
|
def partition(nums, left, right)
|
||||||
# Взять nums[left] в качестве опорного элемента
|
### Использовать 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)
|
med = median_three(nums, left, (left + right) / 2, right)
|
||||||
# Переместить медиану в крайний левый элемент массива
|
# Переместить медиану в крайний левый элемент массива
|
||||||
nums[left], nums[med] = nums[med], nums[left]
|
nums[left], nums[med] = nums[med], nums[left]
|
||||||
@@ -1493,124 +1353,7 @@ class QuickSortMedian
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="quick_sort.rb"
|
```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)
|
def quick_sort(nums, left, right)
|
||||||
# Рекурсивно обрабатывать, пока длина подмассива не станет равной 1
|
# Рекурсивно обрабатывать, пока длина подмассива не станет равной 1
|
||||||
while left < right
|
while left < right
|
||||||
|
|||||||
@@ -669,31 +669,13 @@ $$
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="radix_sort.rb"
|
```ruby title="radix_sort.rb"
|
||||||
=begin
|
### Получить k-й разряд элемента num, где exp = 10^(k-1) ###
|
||||||
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)
|
def digit(num, exp)
|
||||||
# Передача exp вместо k позволяет избежать повторного выполнения дорогостоящих вычислений степени
|
# Передача exp вместо k позволяет избежать повторного выполнения дорогостоящих вычислений степени
|
||||||
(num / exp) % 10
|
(num / exp) % 10
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
### Сортировка подсчетом (сортировка по k-му разряду nums) ###
|
||||||
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)
|
def counting_sort_digit(nums, exp)
|
||||||
# Разряды десятичной системы лежат в диапазоне 0~9, поэтому нужен массив корзин длины 10
|
# Разряды десятичной системы лежат в диапазоне 0~9, поэтому нужен массив корзин длины 10
|
||||||
counter = Array.new(10, 0)
|
counter = Array.new(10, 0)
|
||||||
@@ -717,43 +699,7 @@ $$
|
|||||||
(0...n).each { |i| nums[i] = res[i] }
|
(0...n).each { |i| nums[i] = res[i] }
|
||||||
end
|
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)
|
def radix_sort(nums)
|
||||||
# Получить максимальный элемент массива, чтобы определить максимальное число разрядов
|
# Получить максимальный элемент массива, чтобы определить максимальное число разрядов
|
||||||
m = nums.max
|
m = nums.max
|
||||||
|
|||||||
@@ -306,13 +306,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="selection_sort.rb"
|
```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)
|
def selection_sort(nums)
|
||||||
n = nums.length
|
n = nums.length
|
||||||
# Внешний цикл: неотсортированный диапазон [i, n-1]
|
# Внешний цикл: неотсортированный диапазон [i, n-1]
|
||||||
|
|||||||
@@ -2025,54 +2025,36 @@ comments: true
|
|||||||
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
Author: Xuan Khoa Tu Nguyen (ngxktuzkai2000@gmail.com)
|
||||||
=end
|
=end
|
||||||
|
|
||||||
# ## Узел двусвязного списка
|
### Узел двусвязного списка
|
||||||
class ListNode
|
class ListNode
|
||||||
attr_accessor :val
|
attr_accessor :val
|
||||||
attr_accessor :next # Ссылка на узел-преемник
|
attr_accessor :next # Ссылка на узел-преемник
|
||||||
attr_accessor :prev # Ссылка на узел-предшественник
|
attr_accessor :prev # Ссылка на узел-предшественник
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize(val)
|
def initialize(val)
|
||||||
@val = val
|
@val = val
|
||||||
end
|
end
|
||||||
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
|
class LinkedListDeque
|
||||||
# ## Получение длины двусторонней очереди ###
|
### Получение длины двусторонней очереди ###
|
||||||
attr_reader :size
|
attr_reader :size
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize
|
def initialize
|
||||||
@front = nil # Головной узел front
|
@front = nil # Головной узел front
|
||||||
@rear = nil # Хвостовой узел rear
|
@rear = nil # Хвостовой узел rear
|
||||||
@size = 0 # Длина двусторонней очереди
|
@size = 0 # Длина двусторонней очереди
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Проверка, пуста ли двусторонняя очередь ###
|
### Проверка, пуста ли двусторонняя очередь ###
|
||||||
def is_empty?
|
def is_empty?
|
||||||
size.zero?
|
size.zero?
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция добавления в очередь ###
|
### Операция добавления в очередь ###
|
||||||
def push(num, is_front)
|
def push(num, is_front)
|
||||||
node = ListNode.new(num)
|
node = ListNode.new(num)
|
||||||
# Если связный список пуст, пусть front и rear оба указывают на node
|
# Если связный список пуст, пусть front и rear оба указывают на node
|
||||||
@@ -2094,17 +2076,17 @@ comments: true
|
|||||||
@size += 1 # Обновить длину очереди
|
@size += 1 # Обновить длину очереди
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление в голову очереди ###
|
### Добавление в голову очереди ###
|
||||||
def push_first(num)
|
def push_first(num)
|
||||||
push(num, true)
|
push(num, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление в хвост очереди ###
|
### Добавление в хвост очереди ###
|
||||||
def push_last(num)
|
def push_last(num)
|
||||||
push(num, false)
|
push(num, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Операция извлечения из очереди ###
|
### Операция извлечения из очереди ###
|
||||||
def pop(is_front)
|
def pop(is_front)
|
||||||
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
||||||
|
|
||||||
@@ -2134,31 +2116,31 @@ comments: true
|
|||||||
val
|
val
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Извлечение из головы очереди ###
|
### Извлечение из головы очереди ###
|
||||||
def pop_first
|
def pop_first
|
||||||
pop(true)
|
pop(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Извлечение из головы очереди ###
|
### Извлечение из головы очереди ###
|
||||||
def pop_last
|
def pop_last
|
||||||
pop(false)
|
pop(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к элементу в начале очереди ###
|
### Доступ к элементу в начале очереди ###
|
||||||
def peek_first
|
def peek_first
|
||||||
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
||||||
|
|
||||||
@front.val
|
@front.val
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к элементу в хвосте очереди ###
|
### Доступ к элементу в хвосте очереди ###
|
||||||
def peek_last
|
def peek_last
|
||||||
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
||||||
|
|
||||||
@rear.val
|
@rear.val
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вернуть массив для вывода ###
|
### Вернуть массив для вывода ###
|
||||||
def to_array
|
def to_array
|
||||||
node = @front
|
node = @front
|
||||||
res = Array.new(size, 0)
|
res = Array.new(size, 0)
|
||||||
@@ -3514,35 +3496,29 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array_deque.rb"
|
```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
|
class ArrayDeque
|
||||||
# ## Получение длины двусторонней очереди ###
|
### Получение длины двусторонней очереди ###
|
||||||
attr_reader :size
|
attr_reader :size
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize(capacity)
|
def initialize(capacity)
|
||||||
@nums = Array.new(capacity, 0)
|
@nums = Array.new(capacity, 0)
|
||||||
@front = 0
|
@front = 0
|
||||||
@size = 0
|
@size = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить вместимость двусторонней очереди ###
|
### Получить вместимость двусторонней очереди ###
|
||||||
def capacity
|
def capacity
|
||||||
@nums.length
|
@nums.length
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Проверка, пуста ли двусторонняя очередь ###
|
### Проверка, пуста ли двусторонняя очередь ###
|
||||||
def is_empty?
|
def is_empty?
|
||||||
size.zero?
|
size.zero?
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление в голову очереди ###
|
### Добавление в голову очереди ###
|
||||||
def push_first(num)
|
def push_first(num)
|
||||||
if size == capacity
|
if size == capacity
|
||||||
puts 'Двусторонняя очередь заполнена'
|
puts 'Двусторонняя очередь заполнена'
|
||||||
@@ -3557,7 +3533,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление в хвост очереди ###
|
### Добавление в хвост очереди ###
|
||||||
def push_last(num)
|
def push_last(num)
|
||||||
if size == capacity
|
if size == capacity
|
||||||
puts 'Двусторонняя очередь заполнена'
|
puts 'Двусторонняя очередь заполнена'
|
||||||
@@ -3571,7 +3547,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Извлечение из головы очереди ###
|
### Извлечение из головы очереди ###
|
||||||
def pop_first
|
def pop_first
|
||||||
num = peek_first
|
num = peek_first
|
||||||
# Указатель головы сдвигается на одну позицию назад
|
# Указатель головы сдвигается на одну позицию назад
|
||||||
@@ -3580,21 +3556,21 @@ comments: true
|
|||||||
num
|
num
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Извлечение из хвоста очереди ###
|
### Извлечение из хвоста очереди ###
|
||||||
def pop_last
|
def pop_last
|
||||||
num = peek_last
|
num = peek_last
|
||||||
@size -= 1
|
@size -= 1
|
||||||
num
|
num
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к элементу в начале очереди ###
|
### Доступ к элементу в начале очереди ###
|
||||||
def peek_first
|
def peek_first
|
||||||
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
||||||
|
|
||||||
@nums[@front]
|
@nums[@front]
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к элементу в хвосте очереди ###
|
### Доступ к элементу в хвосте очереди ###
|
||||||
def peek_last
|
def peek_last
|
||||||
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
raise IndexError, 'двусторонняя очередь пуста' if is_empty?
|
||||||
|
|
||||||
@@ -3603,7 +3579,7 @@ comments: true
|
|||||||
@nums[last]
|
@nums[last]
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вернуть массив для вывода ###
|
### Вернуть массив для вывода ###
|
||||||
def to_array
|
def to_array
|
||||||
# Преобразовывать только элементы списка в пределах фактической длины
|
# Преобразовывать только элементы списка в пределах фактической длины
|
||||||
res = []
|
res = []
|
||||||
@@ -3615,7 +3591,7 @@ comments: true
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# ## Вычислить индекс в кольцевом массиве ###
|
### Вычислить индекс в кольцевом массиве ###
|
||||||
def index(i)
|
def index(i)
|
||||||
# С помощью операции взятия по модулю соединить начало и конец массива
|
# С помощью операции взятия по модулю соединить начало и конец массива
|
||||||
# Когда i выходит за конец массива, он возвращается в начало
|
# Когда i выходит за конец массива, он возвращается в начало
|
||||||
|
|||||||
@@ -1246,32 +1246,24 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="linkedlist_queue.rb"
|
```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
|
class LinkedListQueue
|
||||||
# ## Получение длины очереди ###
|
### Получение длины очереди ###
|
||||||
attr_reader :size
|
attr_reader :size
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize
|
def initialize
|
||||||
@front = nil # Головной узел front
|
@front = nil # Головной узел front
|
||||||
@rear = nil # Хвостовой узел rear
|
@rear = nil # Хвостовой узел rear
|
||||||
@size = 0
|
@size = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Проверка, пуста ли очередь ###
|
### Проверка, пуста ли очередь ###
|
||||||
def is_empty?
|
def is_empty?
|
||||||
@front.nil?
|
@front.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление в очередь ###
|
### Добавление в очередь ###
|
||||||
def push(num)
|
def push(num)
|
||||||
# Добавить num после хвостового узла
|
# Добавить num после хвостового узла
|
||||||
node = ListNode.new(num)
|
node = ListNode.new(num)
|
||||||
@@ -1289,7 +1281,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Извлечение из очереди ###
|
### Извлечение из очереди ###
|
||||||
def pop
|
def pop
|
||||||
num = peek
|
num = peek
|
||||||
# Удалить головной узел
|
# Удалить головной узел
|
||||||
@@ -1298,14 +1290,14 @@ comments: true
|
|||||||
num
|
num
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к элементу в начале очереди ###
|
### Доступ к элементу в начале очереди ###
|
||||||
def peek
|
def peek
|
||||||
raise IndexError, 'очередь пуста' if is_empty?
|
raise IndexError, 'очередь пуста' if is_empty?
|
||||||
|
|
||||||
@front.val
|
@front.val
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Преобразовать связный список в Array и вернуть ###
|
### Преобразовать связный список в Array и вернуть ###
|
||||||
def to_array
|
def to_array
|
||||||
queue = []
|
queue = []
|
||||||
temp = @front
|
temp = @front
|
||||||
@@ -2228,35 +2220,29 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array_queue.rb"
|
```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
|
class ArrayQueue
|
||||||
# ## Получение длины очереди ###
|
### Получение длины очереди ###
|
||||||
attr_reader :size
|
attr_reader :size
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize(size)
|
def initialize(size)
|
||||||
@nums = Array.new(size, 0) # Массив для хранения элементов очереди
|
@nums = Array.new(size, 0) # Массив для хранения элементов очереди
|
||||||
@front = 0 # Указатель head, указывающий на первый элемент очереди
|
@front = 0 # Указатель head, указывающий на первый элемент очереди
|
||||||
@size = 0 # Длина очереди
|
@size = 0 # Длина очереди
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить вместимость очереди ###
|
### Получить вместимость очереди ###
|
||||||
def capacity
|
def capacity
|
||||||
@nums.length
|
@nums.length
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Проверка, пуста ли очередь ###
|
### Проверка, пуста ли очередь ###
|
||||||
def is_empty?
|
def is_empty?
|
||||||
size.zero?
|
size.zero?
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Добавление в очередь ###
|
### Добавление в очередь ###
|
||||||
def push(num)
|
def push(num)
|
||||||
raise IndexError, 'очередь заполнена' if size == capacity
|
raise IndexError, 'очередь заполнена' if size == capacity
|
||||||
|
|
||||||
@@ -2268,7 +2254,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Извлечение из очереди ###
|
### Извлечение из очереди ###
|
||||||
def pop
|
def pop
|
||||||
num = peek
|
num = peek
|
||||||
# Указатель head сдвигается на одну позицию назад; если он выходит за конец, то возвращается в начало массива
|
# Указатель head сдвигается на одну позицию назад; если он выходит за конец, то возвращается в начало массива
|
||||||
@@ -2277,14 +2263,14 @@ comments: true
|
|||||||
num
|
num
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к элементу в начале очереди ###
|
### Доступ к элементу в начале очереди ###
|
||||||
def peek
|
def peek
|
||||||
raise IndexError, 'очередь пуста' if is_empty?
|
raise IndexError, 'очередь пуста' if is_empty?
|
||||||
|
|
||||||
@nums[@front]
|
@nums[@front]
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вернуть список для вывода ###
|
### Вернуть список для вывода ###
|
||||||
def to_array
|
def to_array
|
||||||
res = Array.new(size, 0)
|
res = Array.new(size, 0)
|
||||||
j = @front
|
j = @front
|
||||||
|
|||||||
@@ -1109,29 +1109,21 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="linkedlist_stack.rb"
|
```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
|
class LinkedListStack
|
||||||
attr_reader :size
|
attr_reader :size
|
||||||
|
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize
|
def initialize
|
||||||
@size = 0
|
@size = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Проверка, пуст ли стек ###
|
### Проверка, пуст ли стек ###
|
||||||
def is_empty?
|
def is_empty?
|
||||||
@peek.nil?
|
@peek.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Помещение в стек ###
|
### Помещение в стек ###
|
||||||
def push(val)
|
def push(val)
|
||||||
node = ListNode.new(val)
|
node = ListNode.new(val)
|
||||||
node.next = @peek
|
node.next = @peek
|
||||||
@@ -1139,7 +1131,7 @@ comments: true
|
|||||||
@size += 1
|
@size += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Извлечение из стека ###
|
### Извлечение из стека ###
|
||||||
def pop
|
def pop
|
||||||
num = peek
|
num = peek
|
||||||
@peek = @peek.next
|
@peek = @peek.next
|
||||||
@@ -1147,14 +1139,14 @@ comments: true
|
|||||||
num
|
num
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к верхнему элементу стека ###
|
### Доступ к верхнему элементу стека ###
|
||||||
def peek
|
def peek
|
||||||
raise IndexError, 'стек пуст' if is_empty?
|
raise IndexError, 'стек пуст' if is_empty?
|
||||||
|
|
||||||
@peek.val
|
@peek.val
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Преобразовать связный список в Array и вернуть ###
|
### Преобразовать связный список в Array и вернуть ###
|
||||||
def to_array
|
def to_array
|
||||||
arr = []
|
arr = []
|
||||||
node = @peek
|
node = @peek
|
||||||
@@ -1766,49 +1758,43 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array_stack.rb"
|
```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
|
class ArrayStack
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize
|
def initialize
|
||||||
@stack = []
|
@stack = []
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить длину стека ###
|
### Получить длину стека ###
|
||||||
def size
|
def size
|
||||||
@stack.length
|
@stack.length
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Проверка, пуст ли стек ###
|
### Проверка, пуст ли стек ###
|
||||||
def is_empty?
|
def is_empty?
|
||||||
@stack.empty?
|
@stack.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Помещение в стек ###
|
### Помещение в стек ###
|
||||||
def push(item)
|
def push(item)
|
||||||
@stack << item
|
@stack << item
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Извлечение из стека ###
|
### Извлечение из стека ###
|
||||||
def pop
|
def pop
|
||||||
raise IndexError, 'стек пуст' if is_empty?
|
raise IndexError, 'стек пуст' if is_empty?
|
||||||
|
|
||||||
@stack.pop
|
@stack.pop
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Доступ к верхнему элементу стека ###
|
### Доступ к верхнему элементу стека ###
|
||||||
def peek
|
def peek
|
||||||
raise IndexError, 'стек пуст' if is_empty?
|
raise IndexError, 'стек пуст' if is_empty?
|
||||||
|
|
||||||
@stack.last
|
@stack.last
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вернуть список для вывода ###
|
### Вернуть список для вывода ###
|
||||||
def to_array
|
def to_array
|
||||||
@stack
|
@stack
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1245,28 +1245,19 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="array_binary_tree.rb"
|
```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
|
class ArrayBinaryTree
|
||||||
# ## Конструктор ###
|
### Конструктор ###
|
||||||
def initialize(arr)
|
def initialize(arr)
|
||||||
@tree = arr.to_a
|
@tree = arr.to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Вместимость списка ###
|
### Вместимость списка ###
|
||||||
def size
|
def size
|
||||||
@tree.length
|
@tree.length
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить значение узла с индексом i ###
|
### Получить значение узла с индексом i ###
|
||||||
def val(i)
|
def val(i)
|
||||||
# Если индекс выходит за границы, вернуть nil, обозначающий пустую ячейку
|
# Если индекс выходит за границы, вернуть nil, обозначающий пустую ячейку
|
||||||
return if i < 0 || i >= size
|
return if i < 0 || i >= size
|
||||||
@@ -1274,22 +1265,22 @@ comments: true
|
|||||||
@tree[i]
|
@tree[i]
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить индекс левого дочернего узла узла с индексом i ###
|
### Получить индекс левого дочернего узла узла с индексом i ###
|
||||||
def left(i)
|
def left(i)
|
||||||
2 * i + 1
|
2 * i + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить индекс правого дочернего узла узла с индексом i ###
|
### Получить индекс правого дочернего узла узла с индексом i ###
|
||||||
def right(i)
|
def right(i)
|
||||||
2 * i + 2
|
2 * i + 2
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Получить индекс родительского узла узла с индексом i ###
|
### Получить индекс родительского узла узла с индексом i ###
|
||||||
def parent(i)
|
def parent(i)
|
||||||
(i - 1) / 2
|
(i - 1) / 2
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Обход в ширину ###
|
### Обход в ширину ###
|
||||||
def level_order
|
def level_order
|
||||||
@res = []
|
@res = []
|
||||||
|
|
||||||
@@ -1301,7 +1292,7 @@ comments: true
|
|||||||
@res
|
@res
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Обход в глубину ###
|
### Обход в глубину ###
|
||||||
def dfs(i, order)
|
def dfs(i, order)
|
||||||
return if val(i).nil?
|
return if val(i).nil?
|
||||||
# Предварительный обход
|
# Предварительный обход
|
||||||
@@ -1314,21 +1305,21 @@ comments: true
|
|||||||
@res << val(i) if order == :post
|
@res << val(i) if order == :post
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Предварительный обход ###
|
### Предварительный обход ###
|
||||||
def pre_order
|
def pre_order
|
||||||
@res = []
|
@res = []
|
||||||
dfs(0, :pre)
|
dfs(0, :pre)
|
||||||
@res
|
@res
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Симметричный обход ###
|
### Симметричный обход ###
|
||||||
def in_order
|
def in_order
|
||||||
@res = []
|
@res = []
|
||||||
dfs(0, :in)
|
dfs(0, :in)
|
||||||
@res
|
@res
|
||||||
end
|
end
|
||||||
|
|
||||||
# ## Обратный обход ###
|
### Обратный обход ###
|
||||||
def post_order
|
def post_order
|
||||||
@res = []
|
@res = []
|
||||||
dfs(0, :post)
|
dfs(0, :post)
|
||||||
|
|||||||
@@ -460,28 +460,7 @@ AVL-дерево одновременно является и двоичным
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="avl_tree.rb"
|
```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)
|
def height(node)
|
||||||
# Высота пустого узла равна -1, высота листового узла равна 0
|
# Высота пустого узла равна -1, высота листового узла равна 0
|
||||||
return node.height unless node.nil?
|
return node.height unless node.nil?
|
||||||
@@ -489,36 +468,7 @@ AVL-дерево одновременно является и двоичным
|
|||||||
-1
|
-1
|
||||||
end
|
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)
|
def update_height(node)
|
||||||
# Высота узла равна высоте более высокого поддерева + 1
|
# Высота узла равна высоте более высокого поддерева + 1
|
||||||
node.height = [height(node.left), height(node.right)].max + 1
|
node.height = [height(node.left), height(node.right)].max + 1
|
||||||
@@ -686,42 +636,7 @@ AVL-дерево одновременно является и двоичным
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="avl_tree.rb"
|
```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)
|
def balance_factor(node)
|
||||||
# Коэффициент баланса пустого узла равен 0
|
# Коэффициент баланса пустого узла равен 0
|
||||||
return 0 if node.nil?
|
return 0 if node.nil?
|
||||||
@@ -991,51 +906,7 @@ AVL-дерево одновременно является и двоичным
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="avl_tree.rb"
|
```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)
|
def right_rotate(node)
|
||||||
child = node.left
|
child = node.left
|
||||||
grand_child = child.right
|
grand_child = child.right
|
||||||
@@ -1290,65 +1161,7 @@ AVL-дерево одновременно является и двоичным
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="avl_tree.rb"
|
```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)
|
def left_rotate(node)
|
||||||
child = node.right
|
child = node.right
|
||||||
grand_child = child.left
|
grand_child = child.left
|
||||||
@@ -1816,79 +1629,7 @@ AVL-дерево одновременно является и двоичным
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="avl_tree.rb"
|
```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)
|
def rotate(node)
|
||||||
# Получить коэффициент баланса узла node
|
# Получить коэффициент баланса узла node
|
||||||
balance_factor = balance_factor(node)
|
balance_factor = balance_factor(node)
|
||||||
@@ -2272,219 +2013,12 @@ AVL-дерево одновременно является и двоичным
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="avl_tree.rb"
|
```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)
|
def insert(val)
|
||||||
@root = insert_helper(@root, val)
|
@root = insert_helper(@root, val)
|
||||||
end
|
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)
|
def insert_helper(node, val)
|
||||||
return TreeNode.new(val) if node.nil?
|
return TreeNode.new(val) if node.nil?
|
||||||
# 1. Найти позицию вставки и вставить узел
|
# 1. Найти позицию вставки и вставить узел
|
||||||
@@ -3067,265 +2601,12 @@ AVL-дерево одновременно является и двоичным
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="avl_tree.rb"
|
```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)
|
def remove(val)
|
||||||
@root = remove_helper(@root, val)
|
@root = remove_helper(@root, val)
|
||||||
end
|
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)
|
def remove_helper(node, val)
|
||||||
return if node.nil?
|
return if node.nil?
|
||||||
# 1. Найти узел и удалить его
|
# 1. Найти узел и удалить его
|
||||||
|
|||||||
@@ -316,29 +316,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search_tree.rb"
|
```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)
|
def search(num)
|
||||||
cur = @root
|
cur = @root
|
||||||
|
|
||||||
@@ -790,50 +768,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search_tree.rb"
|
```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)
|
def insert(num)
|
||||||
# Если дерево пусто, инициализировать корневой узел
|
# Если дерево пусто, инициализировать корневой узел
|
||||||
if @root.nil?
|
if @root.nil?
|
||||||
@@ -1600,83 +1535,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_search_tree.rb"
|
```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)
|
def remove(num)
|
||||||
# Если дерево пусто, сразу вернуть
|
# Если дерево пусто, сразу вернуть
|
||||||
return if @root.nil?
|
return if @root.nil?
|
||||||
|
|||||||
@@ -318,16 +318,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_tree_bfs.rb"
|
```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)
|
def level_order(root)
|
||||||
# Инициализировать очередь и добавить корневой узел
|
# Инициализировать очередь и добавить корневой узел
|
||||||
queue = [root]
|
queue = [root]
|
||||||
@@ -797,16 +788,7 @@ comments: true
|
|||||||
=== "Ruby"
|
=== "Ruby"
|
||||||
|
|
||||||
```ruby title="binary_tree_dfs.rb"
|
```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)
|
def pre_order(root)
|
||||||
return if root.nil?
|
return if root.nil?
|
||||||
|
|
||||||
@@ -816,26 +798,7 @@ comments: true
|
|||||||
pre_order(root.right)
|
pre_order(root.right)
|
||||||
end
|
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)
|
def in_order(root)
|
||||||
return if root.nil?
|
return if root.nil?
|
||||||
|
|
||||||
@@ -845,36 +808,7 @@ comments: true
|
|||||||
in_order(root.right)
|
in_order(root.right)
|
||||||
end
|
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)
|
def post_order(root)
|
||||||
return if root.nil?
|
return if root.nil?
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user