pandusha 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pandusha/__init__.py +60 -0
- pandusha/avl_tree.py +111 -0
- pandusha/binary_search_tree.py +140 -0
- pandusha/disjoint_set.py +44 -0
- pandusha/doubly_linked_list.py +232 -0
- pandusha/dynamic_programming.py +49 -0
- pandusha/graph.py +159 -0
- pandusha/hash_table.py +65 -0
- pandusha/heap.py +102 -0
- pandusha/linked_list.py +302 -0
- pandusha/queue.py +65 -0
- pandusha/searching.py +43 -0
- pandusha/sorting.py +75 -0
- pandusha/stack.py +56 -0
- pandusha/trie.py +62 -0
- pandusha-0.2.0.dist-info/METADATA +107 -0
- pandusha-0.2.0.dist-info/RECORD +20 -0
- pandusha-0.2.0.dist-info/WHEEL +5 -0
- pandusha-0.2.0.dist-info/licenses/LICENSE +201 -0
- pandusha-0.2.0.dist-info/top_level.txt +1 -0
pandusha/__init__.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Pandusha - educational data structures and algorithms library."""
|
|
2
|
+
|
|
3
|
+
from .avl_tree import AVLTree
|
|
4
|
+
from .binary_search_tree import BinarySearchTree
|
|
5
|
+
from .disjoint_set import DisjointSet
|
|
6
|
+
from .doubly_linked_list import DoublyLinkedList
|
|
7
|
+
from .dynamic_programming import (
|
|
8
|
+
climbing_stairs,
|
|
9
|
+
coin_change_min,
|
|
10
|
+
fibonacci_memo,
|
|
11
|
+
fibonacci_tabulation,
|
|
12
|
+
)
|
|
13
|
+
from .graph import Graph
|
|
14
|
+
from .hash_table import HashTable
|
|
15
|
+
from .heap import MaxHeap, MinHeap, PriorityQueue
|
|
16
|
+
from .linked_list import LinkedList
|
|
17
|
+
from .queue import Queue
|
|
18
|
+
from .searching import binary_search, jump_search, linear_search
|
|
19
|
+
from .sorting import (
|
|
20
|
+
bubble_sort,
|
|
21
|
+
heap_sort,
|
|
22
|
+
insertion_sort,
|
|
23
|
+
merge_sort,
|
|
24
|
+
quick_sort,
|
|
25
|
+
selection_sort,
|
|
26
|
+
)
|
|
27
|
+
from .stack import Stack
|
|
28
|
+
from .trie import Trie
|
|
29
|
+
|
|
30
|
+
__version__ = "0.2.0"
|
|
31
|
+
__author__ = "Cem Berk Çakır, Yasemin Serdengeçti"
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"AVLTree",
|
|
35
|
+
"BinarySearchTree",
|
|
36
|
+
"DisjointSet",
|
|
37
|
+
"DoublyLinkedList",
|
|
38
|
+
"Graph",
|
|
39
|
+
"HashTable",
|
|
40
|
+
"LinkedList",
|
|
41
|
+
"MaxHeap",
|
|
42
|
+
"MinHeap",
|
|
43
|
+
"PriorityQueue",
|
|
44
|
+
"Queue",
|
|
45
|
+
"Stack",
|
|
46
|
+
"Trie",
|
|
47
|
+
"binary_search",
|
|
48
|
+
"bubble_sort",
|
|
49
|
+
"climbing_stairs",
|
|
50
|
+
"coin_change_min",
|
|
51
|
+
"fibonacci_memo",
|
|
52
|
+
"fibonacci_tabulation",
|
|
53
|
+
"heap_sort",
|
|
54
|
+
"insertion_sort",
|
|
55
|
+
"jump_search",
|
|
56
|
+
"linear_search",
|
|
57
|
+
"merge_sort",
|
|
58
|
+
"quick_sort",
|
|
59
|
+
"selection_sort",
|
|
60
|
+
]
|
pandusha/avl_tree.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""AVL tree implementation."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class AVLNode:
|
|
5
|
+
def __init__(self, value):
|
|
6
|
+
self.value = value
|
|
7
|
+
self.left = None
|
|
8
|
+
self.right = None
|
|
9
|
+
self.height = 1
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AVLTree:
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.root = None
|
|
15
|
+
self.length = 0
|
|
16
|
+
|
|
17
|
+
def __iter__(self):
|
|
18
|
+
return iter(self.in_order())
|
|
19
|
+
|
|
20
|
+
def __len__(self):
|
|
21
|
+
return self.length
|
|
22
|
+
|
|
23
|
+
def __repr__(self):
|
|
24
|
+
return f"AVLTree({self.in_order()!r})"
|
|
25
|
+
|
|
26
|
+
def is_empty(self):
|
|
27
|
+
return self.root is None
|
|
28
|
+
|
|
29
|
+
def insert(self, value):
|
|
30
|
+
if self.contains(value):
|
|
31
|
+
return False
|
|
32
|
+
self.root = self._insert(self.root, value)
|
|
33
|
+
self.length += 1
|
|
34
|
+
return True
|
|
35
|
+
|
|
36
|
+
def contains(self, value):
|
|
37
|
+
current = self.root
|
|
38
|
+
while current is not None:
|
|
39
|
+
if value == current.value:
|
|
40
|
+
return True
|
|
41
|
+
current = current.left if value < current.value else current.right
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
def in_order(self):
|
|
45
|
+
values = []
|
|
46
|
+
|
|
47
|
+
def walk(node):
|
|
48
|
+
if node is None:
|
|
49
|
+
return
|
|
50
|
+
walk(node.left)
|
|
51
|
+
values.append(node.value)
|
|
52
|
+
walk(node.right)
|
|
53
|
+
|
|
54
|
+
walk(self.root)
|
|
55
|
+
return values
|
|
56
|
+
|
|
57
|
+
def to_list(self):
|
|
58
|
+
return self.in_order()
|
|
59
|
+
|
|
60
|
+
def height(self):
|
|
61
|
+
return self._height(self.root)
|
|
62
|
+
|
|
63
|
+
def _insert(self, node, value):
|
|
64
|
+
if node is None:
|
|
65
|
+
return AVLNode(value)
|
|
66
|
+
if value < node.value:
|
|
67
|
+
node.left = self._insert(node.left, value)
|
|
68
|
+
else:
|
|
69
|
+
node.right = self._insert(node.right, value)
|
|
70
|
+
return self._rebalance(node)
|
|
71
|
+
|
|
72
|
+
def _height(self, node):
|
|
73
|
+
return node.height if node is not None else 0
|
|
74
|
+
|
|
75
|
+
def _balance(self, node):
|
|
76
|
+
return self._height(node.left) - self._height(node.right) if node is not None else 0
|
|
77
|
+
|
|
78
|
+
def _update_height(self, node):
|
|
79
|
+
node.height = 1 + max(self._height(node.left), self._height(node.right))
|
|
80
|
+
|
|
81
|
+
def _rebalance(self, node):
|
|
82
|
+
self._update_height(node)
|
|
83
|
+
balance = self._balance(node)
|
|
84
|
+
|
|
85
|
+
if balance > 1:
|
|
86
|
+
if self._balance(node.left) < 0:
|
|
87
|
+
node.left = self._rotate_left(node.left)
|
|
88
|
+
return self._rotate_right(node)
|
|
89
|
+
if balance < -1:
|
|
90
|
+
if self._balance(node.right) > 0:
|
|
91
|
+
node.right = self._rotate_right(node.right)
|
|
92
|
+
return self._rotate_left(node)
|
|
93
|
+
return node
|
|
94
|
+
|
|
95
|
+
def _rotate_left(self, node):
|
|
96
|
+
new_root = node.right
|
|
97
|
+
moved_subtree = new_root.left
|
|
98
|
+
new_root.left = node
|
|
99
|
+
node.right = moved_subtree
|
|
100
|
+
self._update_height(node)
|
|
101
|
+
self._update_height(new_root)
|
|
102
|
+
return new_root
|
|
103
|
+
|
|
104
|
+
def _rotate_right(self, node):
|
|
105
|
+
new_root = node.left
|
|
106
|
+
moved_subtree = new_root.right
|
|
107
|
+
new_root.right = node
|
|
108
|
+
node.left = moved_subtree
|
|
109
|
+
self._update_height(node)
|
|
110
|
+
self._update_height(new_root)
|
|
111
|
+
return new_root
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""Binary search tree implementation."""
|
|
2
|
+
|
|
3
|
+
from collections import deque
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Node:
|
|
7
|
+
def __init__(self, value):
|
|
8
|
+
self.value = value
|
|
9
|
+
self.left = None
|
|
10
|
+
self.right = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BinarySearchTree:
|
|
14
|
+
def __init__(self):
|
|
15
|
+
self.root = None
|
|
16
|
+
self.length = 0
|
|
17
|
+
|
|
18
|
+
def __iter__(self):
|
|
19
|
+
return iter(self.in_order())
|
|
20
|
+
|
|
21
|
+
def __len__(self):
|
|
22
|
+
return self.length
|
|
23
|
+
|
|
24
|
+
def __repr__(self):
|
|
25
|
+
return f"BinarySearchTree({self.to_list()!r})"
|
|
26
|
+
|
|
27
|
+
def is_empty(self):
|
|
28
|
+
return self.root is None
|
|
29
|
+
|
|
30
|
+
def to_list(self):
|
|
31
|
+
return self.in_order()
|
|
32
|
+
|
|
33
|
+
def insert(self, value):
|
|
34
|
+
new_node = Node(value)
|
|
35
|
+
if self.root is None:
|
|
36
|
+
self.root = new_node
|
|
37
|
+
self.length += 1
|
|
38
|
+
return True
|
|
39
|
+
|
|
40
|
+
current = self.root
|
|
41
|
+
while True:
|
|
42
|
+
if value == current.value:
|
|
43
|
+
return False
|
|
44
|
+
if value < current.value:
|
|
45
|
+
if current.left is None:
|
|
46
|
+
current.left = new_node
|
|
47
|
+
self.length += 1
|
|
48
|
+
return True
|
|
49
|
+
current = current.left
|
|
50
|
+
else:
|
|
51
|
+
if current.right is None:
|
|
52
|
+
current.right = new_node
|
|
53
|
+
self.length += 1
|
|
54
|
+
return True
|
|
55
|
+
current = current.right
|
|
56
|
+
|
|
57
|
+
def contains(self, value):
|
|
58
|
+
current = self.root
|
|
59
|
+
while current is not None:
|
|
60
|
+
if value == current.value:
|
|
61
|
+
return True
|
|
62
|
+
current = current.left if value < current.value else current.right
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
def in_order(self):
|
|
66
|
+
values = []
|
|
67
|
+
|
|
68
|
+
def walk(node):
|
|
69
|
+
if node is None:
|
|
70
|
+
return
|
|
71
|
+
walk(node.left)
|
|
72
|
+
values.append(node.value)
|
|
73
|
+
walk(node.right)
|
|
74
|
+
|
|
75
|
+
walk(self.root)
|
|
76
|
+
return values
|
|
77
|
+
|
|
78
|
+
def pre_order(self):
|
|
79
|
+
values = []
|
|
80
|
+
|
|
81
|
+
def walk(node):
|
|
82
|
+
if node is None:
|
|
83
|
+
return
|
|
84
|
+
values.append(node.value)
|
|
85
|
+
walk(node.left)
|
|
86
|
+
walk(node.right)
|
|
87
|
+
|
|
88
|
+
walk(self.root)
|
|
89
|
+
return values
|
|
90
|
+
|
|
91
|
+
def post_order(self):
|
|
92
|
+
values = []
|
|
93
|
+
|
|
94
|
+
def walk(node):
|
|
95
|
+
if node is None:
|
|
96
|
+
return
|
|
97
|
+
walk(node.left)
|
|
98
|
+
walk(node.right)
|
|
99
|
+
values.append(node.value)
|
|
100
|
+
|
|
101
|
+
walk(self.root)
|
|
102
|
+
return values
|
|
103
|
+
|
|
104
|
+
def level_order(self):
|
|
105
|
+
if self.root is None:
|
|
106
|
+
return []
|
|
107
|
+
values = []
|
|
108
|
+
queue = deque([self.root])
|
|
109
|
+
while queue:
|
|
110
|
+
node = queue.popleft()
|
|
111
|
+
values.append(node.value)
|
|
112
|
+
if node.left is not None:
|
|
113
|
+
queue.append(node.left)
|
|
114
|
+
if node.right is not None:
|
|
115
|
+
queue.append(node.right)
|
|
116
|
+
return values
|
|
117
|
+
|
|
118
|
+
def min_value(self):
|
|
119
|
+
current = self.root
|
|
120
|
+
if current is None:
|
|
121
|
+
return None
|
|
122
|
+
while current.left is not None:
|
|
123
|
+
current = current.left
|
|
124
|
+
return current.value
|
|
125
|
+
|
|
126
|
+
def max_value(self):
|
|
127
|
+
current = self.root
|
|
128
|
+
if current is None:
|
|
129
|
+
return None
|
|
130
|
+
while current.right is not None:
|
|
131
|
+
current = current.right
|
|
132
|
+
return current.value
|
|
133
|
+
|
|
134
|
+
def height(self):
|
|
135
|
+
def walk(node):
|
|
136
|
+
if node is None:
|
|
137
|
+
return 0
|
|
138
|
+
return 1 + max(walk(node.left), walk(node.right))
|
|
139
|
+
|
|
140
|
+
return walk(self.root)
|
pandusha/disjoint_set.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Disjoint set / union-find implementation."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DisjointSet:
|
|
5
|
+
def __init__(self):
|
|
6
|
+
self.parent = {}
|
|
7
|
+
self.rank = {}
|
|
8
|
+
|
|
9
|
+
def __len__(self):
|
|
10
|
+
return len(self.parent)
|
|
11
|
+
|
|
12
|
+
def make_set(self, item):
|
|
13
|
+
if item in self.parent:
|
|
14
|
+
return False
|
|
15
|
+
self.parent[item] = item
|
|
16
|
+
self.rank[item] = 0
|
|
17
|
+
return True
|
|
18
|
+
|
|
19
|
+
def find(self, item):
|
|
20
|
+
if item not in self.parent:
|
|
21
|
+
self.make_set(item)
|
|
22
|
+
if self.parent[item] != item:
|
|
23
|
+
self.parent[item] = self.find(self.parent[item])
|
|
24
|
+
return self.parent[item]
|
|
25
|
+
|
|
26
|
+
def union(self, first, second):
|
|
27
|
+
root_first = self.find(first)
|
|
28
|
+
root_second = self.find(second)
|
|
29
|
+
if root_first == root_second:
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
if self.rank[root_first] < self.rank[root_second]:
|
|
33
|
+
self.parent[root_first] = root_second
|
|
34
|
+
elif self.rank[root_first] > self.rank[root_second]:
|
|
35
|
+
self.parent[root_second] = root_first
|
|
36
|
+
else:
|
|
37
|
+
self.parent[root_second] = root_first
|
|
38
|
+
self.rank[root_first] += 1
|
|
39
|
+
return True
|
|
40
|
+
|
|
41
|
+
def connected(self, first, second):
|
|
42
|
+
if first not in self.parent or second not in self.parent:
|
|
43
|
+
return False
|
|
44
|
+
return self.find(first) == self.find(second)
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""Doubly linked list implementation."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
_MISSING = object()
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DoublyLinkedList:
|
|
8
|
+
class Node:
|
|
9
|
+
def __init__(self, value):
|
|
10
|
+
self.value = value
|
|
11
|
+
self.next = None
|
|
12
|
+
self.prev = None
|
|
13
|
+
|
|
14
|
+
def __repr__(self):
|
|
15
|
+
return f"Node({self.value!r})"
|
|
16
|
+
|
|
17
|
+
def __init__(self, value=_MISSING):
|
|
18
|
+
self.head = None
|
|
19
|
+
self.tail = None
|
|
20
|
+
self.length = 0
|
|
21
|
+
if value is not _MISSING:
|
|
22
|
+
self.append(value)
|
|
23
|
+
|
|
24
|
+
def __iter__(self):
|
|
25
|
+
current = self.head
|
|
26
|
+
while current is not None:
|
|
27
|
+
yield current.value
|
|
28
|
+
current = current.next
|
|
29
|
+
|
|
30
|
+
def __len__(self):
|
|
31
|
+
return self.length
|
|
32
|
+
|
|
33
|
+
def __repr__(self):
|
|
34
|
+
return f"DoublyLinkedList({self.to_list()!r})"
|
|
35
|
+
|
|
36
|
+
def get_head(self):
|
|
37
|
+
return self.head
|
|
38
|
+
|
|
39
|
+
def get_tail(self):
|
|
40
|
+
return self.tail
|
|
41
|
+
|
|
42
|
+
def get_length(self):
|
|
43
|
+
return self.length
|
|
44
|
+
|
|
45
|
+
def is_empty(self):
|
|
46
|
+
return self.length == 0
|
|
47
|
+
|
|
48
|
+
def to_list(self):
|
|
49
|
+
return list(self)
|
|
50
|
+
|
|
51
|
+
def print_list(self):
|
|
52
|
+
current = self.head
|
|
53
|
+
while current is not None:
|
|
54
|
+
print(current.value)
|
|
55
|
+
current = current.next
|
|
56
|
+
|
|
57
|
+
def print_all(self):
|
|
58
|
+
print("Head:", self.head.value if self.head else "Null")
|
|
59
|
+
print("Tail:", self.tail.value if self.tail else "Null")
|
|
60
|
+
print("Length:", self.length)
|
|
61
|
+
print("\nDoubly Linked List:")
|
|
62
|
+
if self.is_empty():
|
|
63
|
+
print("Empty")
|
|
64
|
+
else:
|
|
65
|
+
self.print_list()
|
|
66
|
+
|
|
67
|
+
def make_empty(self):
|
|
68
|
+
self.head = None
|
|
69
|
+
self.tail = None
|
|
70
|
+
self.length = 0
|
|
71
|
+
|
|
72
|
+
def clear(self):
|
|
73
|
+
self.make_empty()
|
|
74
|
+
|
|
75
|
+
def append(self, value):
|
|
76
|
+
new_node = self.Node(value)
|
|
77
|
+
if self.is_empty():
|
|
78
|
+
self.head = new_node
|
|
79
|
+
self.tail = new_node
|
|
80
|
+
else:
|
|
81
|
+
self.tail.next = new_node
|
|
82
|
+
new_node.prev = self.tail
|
|
83
|
+
self.tail = new_node
|
|
84
|
+
self.length += 1
|
|
85
|
+
return True
|
|
86
|
+
|
|
87
|
+
def remove_last(self):
|
|
88
|
+
if self.is_empty():
|
|
89
|
+
return None
|
|
90
|
+
temp = self.tail
|
|
91
|
+
if self.length == 1:
|
|
92
|
+
self.make_empty()
|
|
93
|
+
return temp
|
|
94
|
+
else:
|
|
95
|
+
self.tail = self.tail.prev
|
|
96
|
+
self.tail.next = None
|
|
97
|
+
temp.prev = None
|
|
98
|
+
self.length -= 1
|
|
99
|
+
return temp
|
|
100
|
+
|
|
101
|
+
def prepend(self, value):
|
|
102
|
+
new_node = self.Node(value)
|
|
103
|
+
if self.is_empty():
|
|
104
|
+
self.head = new_node
|
|
105
|
+
self.tail = new_node
|
|
106
|
+
else:
|
|
107
|
+
new_node.next = self.head
|
|
108
|
+
self.head.prev = new_node
|
|
109
|
+
self.head = new_node
|
|
110
|
+
self.length += 1
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
def remove_first(self):
|
|
114
|
+
if self.is_empty():
|
|
115
|
+
return None
|
|
116
|
+
temp = self.head
|
|
117
|
+
if self.length == 1:
|
|
118
|
+
self.make_empty()
|
|
119
|
+
else:
|
|
120
|
+
self.head = self.head.next
|
|
121
|
+
self.head.prev = None
|
|
122
|
+
temp.next = None
|
|
123
|
+
self.length -= 1
|
|
124
|
+
return temp
|
|
125
|
+
|
|
126
|
+
def get(self, index):
|
|
127
|
+
if index < 0 or index >= self.length:
|
|
128
|
+
return None
|
|
129
|
+
if index < self.length / 2:
|
|
130
|
+
current = self.head
|
|
131
|
+
for _ in range(index):
|
|
132
|
+
current = current.next
|
|
133
|
+
else:
|
|
134
|
+
current = self.tail
|
|
135
|
+
for _ in range(self.length - 1, index, -1):
|
|
136
|
+
current = current.prev
|
|
137
|
+
return current
|
|
138
|
+
|
|
139
|
+
def set(self, index, value):
|
|
140
|
+
temp = self.get(index)
|
|
141
|
+
if temp is None:
|
|
142
|
+
return False
|
|
143
|
+
temp.value = value
|
|
144
|
+
return True
|
|
145
|
+
|
|
146
|
+
def set_value(self, index, value):
|
|
147
|
+
return self.set(index, value)
|
|
148
|
+
|
|
149
|
+
def insert(self, index, value):
|
|
150
|
+
if index < 0 or index > self.length:
|
|
151
|
+
return False
|
|
152
|
+
if index == 0:
|
|
153
|
+
return self.prepend(value)
|
|
154
|
+
if index == self.length:
|
|
155
|
+
return self.append(value)
|
|
156
|
+
|
|
157
|
+
new_node = self.Node(value)
|
|
158
|
+
before = self.get(index - 1)
|
|
159
|
+
after = before.next
|
|
160
|
+
new_node.prev = before
|
|
161
|
+
new_node.next = after
|
|
162
|
+
before.next = new_node
|
|
163
|
+
after.prev = new_node
|
|
164
|
+
self.length += 1
|
|
165
|
+
return True
|
|
166
|
+
|
|
167
|
+
def remove(self, index):
|
|
168
|
+
if index < 0 or index >= self.length:
|
|
169
|
+
return None
|
|
170
|
+
if index == 0:
|
|
171
|
+
return self.remove_first()
|
|
172
|
+
if index == self.length - 1:
|
|
173
|
+
return self.remove_last()
|
|
174
|
+
|
|
175
|
+
temp = self.get(index)
|
|
176
|
+
temp.prev.next = temp.next
|
|
177
|
+
temp.next.prev = temp.prev
|
|
178
|
+
temp.prev = None
|
|
179
|
+
temp.next = None
|
|
180
|
+
self.length -= 1
|
|
181
|
+
return temp
|
|
182
|
+
|
|
183
|
+
def is_palindrome(self):
|
|
184
|
+
left = self.head
|
|
185
|
+
right = self.tail
|
|
186
|
+
while left is not None and right is not None and left != right and left.prev != right:
|
|
187
|
+
if left.value != right.value:
|
|
188
|
+
return False
|
|
189
|
+
left = left.next
|
|
190
|
+
right = right.prev
|
|
191
|
+
return True
|
|
192
|
+
|
|
193
|
+
def reverse(self):
|
|
194
|
+
current = self.head
|
|
195
|
+
self.head, self.tail = self.tail, self.head
|
|
196
|
+
while current is not None:
|
|
197
|
+
current.prev, current.next = current.next, current.prev
|
|
198
|
+
current = current.prev
|
|
199
|
+
|
|
200
|
+
def partition_list(self, x):
|
|
201
|
+
less = []
|
|
202
|
+
greater_or_equal = []
|
|
203
|
+
current = self.head
|
|
204
|
+
while current is not None:
|
|
205
|
+
if current.value < x:
|
|
206
|
+
less.append(current.value)
|
|
207
|
+
else:
|
|
208
|
+
greater_or_equal.append(current.value)
|
|
209
|
+
current = current.next
|
|
210
|
+
self.make_empty()
|
|
211
|
+
for value in less + greater_or_equal:
|
|
212
|
+
self.append(value)
|
|
213
|
+
|
|
214
|
+
def reverse_between(self, start, end):
|
|
215
|
+
if self.head is None or start == end:
|
|
216
|
+
return
|
|
217
|
+
if start < 0 or end < start or end >= self.length:
|
|
218
|
+
return
|
|
219
|
+
|
|
220
|
+
values = self.to_list()
|
|
221
|
+
values[start : end + 1] = reversed(values[start : end + 1])
|
|
222
|
+
self.make_empty()
|
|
223
|
+
for value in values:
|
|
224
|
+
self.append(value)
|
|
225
|
+
|
|
226
|
+
def swap_pairs(self):
|
|
227
|
+
values = self.to_list()
|
|
228
|
+
for index in range(0, len(values) - 1, 2):
|
|
229
|
+
values[index], values[index + 1] = values[index + 1], values[index]
|
|
230
|
+
self.make_empty()
|
|
231
|
+
for value in values:
|
|
232
|
+
self.append(value)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Small dynamic programming examples."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def fibonacci_memo(n, memo=None):
|
|
5
|
+
if n < 0:
|
|
6
|
+
raise ValueError("n must be non-negative")
|
|
7
|
+
if memo is None:
|
|
8
|
+
memo = {}
|
|
9
|
+
if n in (0, 1):
|
|
10
|
+
return n
|
|
11
|
+
if n not in memo:
|
|
12
|
+
memo[n] = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)
|
|
13
|
+
return memo[n]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def fibonacci_tabulation(n):
|
|
17
|
+
if n < 0:
|
|
18
|
+
raise ValueError("n must be non-negative")
|
|
19
|
+
if n in (0, 1):
|
|
20
|
+
return n
|
|
21
|
+
table = [0] * (n + 1)
|
|
22
|
+
table[1] = 1
|
|
23
|
+
for index in range(2, n + 1):
|
|
24
|
+
table[index] = table[index - 1] + table[index - 2]
|
|
25
|
+
return table[n]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def climbing_stairs(n):
|
|
29
|
+
if n < 0:
|
|
30
|
+
raise ValueError("n must be non-negative")
|
|
31
|
+
if n <= 1:
|
|
32
|
+
return 1
|
|
33
|
+
previous = 1
|
|
34
|
+
current = 1
|
|
35
|
+
for _ in range(2, n + 1):
|
|
36
|
+
previous, current = current, previous + current
|
|
37
|
+
return current
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def coin_change_min(coins, amount):
|
|
41
|
+
if amount < 0:
|
|
42
|
+
raise ValueError("amount must be non-negative")
|
|
43
|
+
dp = [float("inf")] * (amount + 1)
|
|
44
|
+
dp[0] = 0
|
|
45
|
+
for value in range(1, amount + 1):
|
|
46
|
+
for coin in coins:
|
|
47
|
+
if coin <= value:
|
|
48
|
+
dp[value] = min(dp[value], dp[value - coin] + 1)
|
|
49
|
+
return dp[amount] if dp[amount] != float("inf") else -1
|