├── README.md └── src ├── chapter1 ├── part2 │ └── TimeComplex.py └── part3 │ └── SpaceComplex.py ├── chapter2 ├── part1 │ ├── ListOperator.py │ └── MyArray.py ├── part2 │ └── MyLinkedList.py └── part3 │ └── MyQueue.py ├── chapter3 ├── part2 │ ├── BinaryTreeTraversal.py │ ├── BinaryTreeTraversalLevel.py │ └── BinaryTreeTraversalStack.py ├── part3 │ └── HeapOperator.py └── part4 │ └── PriorityQueue.py ├── chapter4 ├── part2 │ ├── BubbleSort.py │ └── CockTailSort.py ├── part3 │ ├── QuickSort.py │ └── QuickSortWithStack.py ├── part4 │ └── HeapSort.py └── part5 │ ├── BucketSort.py │ └── CountSort.py ├── chapter5 ├── part10 │ └── BigNumberSum.py ├── part11 │ └── GoldMining.py ├── part12 │ └── MedianSortedArrays.py ├── part13 │ └── FindLostNum.py ├── part2 │ └── LinkedListCycle.py ├── part3 │ └── MinStack.py ├── part4 │ └── GreatestCommonDivisor.py ├── part5 │ └── PowerOf2.py ├── part6 │ └── MaxSortedDistance.py ├── part7 │ └── StackQueue.py ├── part8 │ └── FindNearestNumber.py └── part9 │ └── RemoveKDigits.py └── chapter6 ├── __init__.py ├── part2 └── MyBitmap.py ├── part3 └── LRUCache.py ├── part4 └── AStar.py └── part5 └── Redpackage.py /README.md: -------------------------------------------------------------------------------- 1 | 来到这里的朋友们,很高兴你们能看到小灰的拙作。 小灰把书中各个章节所涉及到的代码,都总结到了这个项目当中,让大家可以更方便地学习和调试。 小伙伴们对代码有哪些问题和意见,也欢迎向小灰提出,在这里感谢大家的支持! 2 | 3 | 最后,欢迎大家关注小灰的技术公众号: 程序员小灰(ID:chengxuyuanxiaohui) 4 | 5 | 祝大家在算法的道路上学有所成! 6 | -------------------------------------------------------------------------------- /src/chapter1/part2/TimeComplex.py: -------------------------------------------------------------------------------- 1 | def eat1(n): 2 | for i in range(n): 3 | print("等待1min") 4 | print("等待1min") 5 | print("吃1cm面包") 6 | 7 | 8 | def eat2(n): 9 | while n > 1: 10 | print("等待1min") 11 | print("等待1min") 12 | print("等待1min") 13 | print("等待1min") 14 | print("吃一半面包") 15 | n /= 2 16 | 17 | 18 | def eat3(n): 19 | print("等待1min") 20 | print("吃一个鸡腿") 21 | 22 | 23 | def eat4(n): 24 | for i in range(n): 25 | for j in range(i): 26 | print("等待1min") 27 | print("吃1cm面包") 28 | 29 | 30 | eat4(16) 31 | -------------------------------------------------------------------------------- /src/chapter1/part3/SpaceComplex.py: -------------------------------------------------------------------------------- 1 | def fun1(n): 2 | i = 3 3 | # do something 4 | 5 | 6 | def fun2(n): 7 | array = [0] * n 8 | # do something 9 | 10 | 11 | def fun3(n): 12 | matrix = [[0] * n] * n 13 | # do something 14 | 15 | 16 | def fun4(n): 17 | if n > 0: 18 | fun4(n-1) 19 | # do something 20 | 21 | 22 | fun2(10) 23 | -------------------------------------------------------------------------------- /src/chapter2/part1/ListOperator.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def operate_list(): 4 | # 初始化列表 5 | my_list = [3, 1, 2, 5, 4, 9, 7, 2] 6 | 7 | # 读取元素 8 | print(my_list[2]) 9 | 10 | # 更新元素 11 | my_list[3] = 10 12 | print(my_list[3]) 13 | 14 | # 尾部插入元素 15 | my_list.append(6) 16 | print(my_list) 17 | 18 | # 中间插入元素 19 | my_list.insert(5, 11) 20 | print(my_list) 21 | 22 | # 删除元素 23 | my_list.remove(6) 24 | print(my_list) 25 | 26 | 27 | operate_list() 28 | -------------------------------------------------------------------------------- /src/chapter2/part1/MyArray.py: -------------------------------------------------------------------------------- 1 | 2 | class MyArray: 3 | def __init__(self, capacity): 4 | self.array = [None] * capacity 5 | self.size = 0 6 | 7 | def insert(self, index, element): 8 | # 判断访问下标是否超出范围 9 | if index < 0 or index > self.size: 10 | raise Exception("超出数组实际元素范围!") 11 | # 从右向左循环,逐个元素向右挪一位。 12 | for i in range(self.size-1, index-1, -1): 13 | self.array[i+1] = self.array[i] 14 | # 腾出的位置放入新元素 15 | self.array[index] = element 16 | self.size += 1 17 | 18 | def insert_v2(self, index, element): 19 | # 判断访问下标是否超出范围 20 | if index < 0 or index > self.size: 21 | raise Exception("超出数组实际元素范围!") 22 | # 如果实际元素达到数组容量上线,数组扩容 23 | if self.size >= len(self.array): 24 | self.resize() 25 | # 从右向左循环,逐个元素向右挪一位。 26 | for i in range(self.size-1, index-1, -1): 27 | self.array[i+1] = self.array[i] 28 | # 腾出的位置放入新元素 29 | self.array[index] = element 30 | self.size += 1 31 | 32 | def resize(self): 33 | array_new = [None] * len(self.array) * 2 34 | # 从旧数组拷贝到新数组 35 | for i in range(self.size): 36 | array_new[i] = self.array[i] 37 | self.array = array_new 38 | 39 | def remove(self, index): 40 | # 判断访问下标是否超出范围 41 | if index < 0 or index >= self.size: 42 | raise Exception("超出数组实际元素范围!") 43 | # 从左到右,逐个元素向左挪动一位 44 | for i in range(index, self.size-1): 45 | self.array[i] = self.array[i+1] 46 | self.size -= 1 47 | 48 | def output(self): 49 | for i in range(self.size): 50 | print(self.array[i]) 51 | 52 | 53 | array = MyArray(4) 54 | array.insert_v2(0, 10) 55 | array.insert_v2(1, 11) 56 | array.insert_v2(2, 12) 57 | array.insert_v2(3, 13) 58 | array.insert_v2(4, 14) 59 | array.insert_v2(2, 15) 60 | array.insert_v2(2, 16) 61 | array.insert_v2(2, 17) 62 | array.remove(0) 63 | array.output() 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/chapter2/part2/MyLinkedList.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | class LinkedList: 8 | def __init__(self): 9 | self.size = 0 10 | self.head = None 11 | self.last = None 12 | 13 | def get(self, index): 14 | if index < 0 or index >= self.size: 15 | raise Exception("超出链表节点范围!") 16 | p = self.head 17 | for i in range(index): 18 | p = p.next 19 | return p 20 | 21 | def insert(self, data, index): 22 | if index < 0 or index > self.size: 23 | raise Exception("超出链表节点范围!") 24 | node = Node(data) 25 | if self.size == 0: 26 | # 空链表 27 | self.head = node 28 | self.last = node 29 | elif index == 0: 30 | # 插入头部 31 | node.next = self.head 32 | self.head = node 33 | elif self.size == index: 34 | # 插入尾部 35 | self.last.next = node 36 | self.last = node 37 | else: 38 | # 插入中间 39 | prev_node = self.get(index-1) 40 | node.next = prev_node.next 41 | prev_node.next = node 42 | self.size += 1 43 | 44 | def remove(self, index): 45 | if index < 0 or index >= self.size: 46 | raise Exception("超出链表节点范围!") 47 | # 暂存被删除的节点,用于返回 48 | if index == 0: 49 | # 删除头节点 50 | removed_node = self.head 51 | self.head = self.head.next 52 | if self.size == 1: 53 | self.last == Node 54 | elif index == self.size - 1: 55 | # 删除尾节点 56 | prev_node = self.get(index-1) 57 | removed_node = prev_node.next 58 | prev_node.next = None 59 | self.last = prev_node 60 | else: 61 | # 删除中间节点 62 | prev_node = self.get(index-1) 63 | next_node = prev_node.next.next 64 | removed_node = prev_node.next 65 | prev_node.next = next_node 66 | self.size -= 1 67 | return removed_node 68 | 69 | def output(self): 70 | p = self.head 71 | while p is not None: 72 | print(p.data) 73 | p = p.next 74 | 75 | 76 | linkedList = LinkedList() 77 | linkedList.insert(3, 0) 78 | linkedList.insert(4, 0) 79 | linkedList.insert(9, 2) 80 | linkedList.insert(5, 3) 81 | linkedList.insert(6, 1) 82 | linkedList.remove(0) 83 | linkedList.output() 84 | -------------------------------------------------------------------------------- /src/chapter2/part3/MyQueue.py: -------------------------------------------------------------------------------- 1 | 2 | class MyQueue: 3 | def __init__(self, capacity): 4 | self.list = [None] * capacity 5 | self.front = 0 6 | self.rear = 0 7 | 8 | def enqueue(self, element): 9 | if (self.rear+1) % len(self.list) == self.front: 10 | raise Exception("队列已满 !") 11 | self.list[self.rear] = element 12 | self.rear = (self.rear+1) % len(self.list) 13 | 14 | def dequeue(self): 15 | if self.rear == self.front: 16 | raise Exception("队列为空 !") 17 | dequeue_element = self.list[self.front] 18 | self.front = (self.front+1) % len(self.list) 19 | return dequeue_element 20 | 21 | def output(self): 22 | i = self.front 23 | while i != self.rear: 24 | print(self.list[i]) 25 | i = (i+1) % len(self.list) 26 | 27 | 28 | myQueue = MyQueue(6) 29 | myQueue.enqueue(3) 30 | myQueue.enqueue(5) 31 | myQueue.enqueue(6) 32 | myQueue.dequeue() 33 | myQueue.dequeue() 34 | myQueue.enqueue(2) 35 | myQueue.enqueue(4) 36 | myQueue.output() 37 | -------------------------------------------------------------------------------- /src/chapter3/part2/BinaryTreeTraversal.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class TreeNode: 4 | def __init__(self, data): 5 | self.data = data 6 | self.left = None 7 | self.right = None 8 | 9 | 10 | def create_binary_tree(input_list=[]): 11 | """ 12 | 构建二叉树 13 | :param input_list: 输入数列 14 | """ 15 | if input_list is None or len(input_list) == 0: 16 | return None 17 | data = input_list.pop(0) 18 | if data is None: 19 | return None 20 | node = TreeNode(data) 21 | node.left = create_binary_tree(input_list) 22 | node.right = create_binary_tree(input_list) 23 | return node 24 | 25 | 26 | def pre_order_traversal(node): 27 | """ 28 | 前序遍历 29 | :param node: 二叉树节点 30 | """ 31 | if node is None: 32 | return 33 | print(node.data) 34 | pre_order_traversal(node.left) 35 | pre_order_traversal(node.right) 36 | return node 37 | 38 | 39 | def in_order_traversal(node): 40 | """ 41 | 中序遍历 42 | :param node: 二叉树节点 43 | """ 44 | if node is None: 45 | return 46 | in_order_traversal(node.left) 47 | print(node.data) 48 | in_order_traversal(node.right) 49 | return node 50 | 51 | 52 | def post_order_traversal(node): 53 | """ 54 | 后序遍历 55 | :param node: 二叉树节点 56 | """ 57 | if node is None: 58 | return 59 | post_order_traversal(node.left) 60 | post_order_traversal(node.right) 61 | print(node.data) 62 | return node 63 | 64 | 65 | my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4]) 66 | root = create_binary_tree(my_input_list) 67 | print("前序遍历:") 68 | pre_order_traversal(root) 69 | print("中序遍历:") 70 | in_order_traversal(root) 71 | print("后序遍历:") 72 | post_order_traversal(root) 73 | 74 | -------------------------------------------------------------------------------- /src/chapter3/part2/BinaryTreeTraversalLevel.py: -------------------------------------------------------------------------------- 1 | from queue import Queue 2 | 3 | 4 | def level_order_traversal(node): 5 | queue = Queue() 6 | queue.put(node) 7 | while not queue.empty(): 8 | node = queue.get() 9 | print(node.data) 10 | if node.left is not None: 11 | queue.put(node.left) 12 | if node.right is not None: 13 | queue.put(node.right) 14 | 15 | 16 | def create_binary_tree(input_list=[]): 17 | if input_list is None or len(input_list) == 0: 18 | return None 19 | data = input_list.pop(0) 20 | if data is None: 21 | return None 22 | node = TreeNode(data) 23 | node.left = create_binary_tree(input_list) 24 | node.right = create_binary_tree(input_list) 25 | return node 26 | 27 | 28 | class TreeNode: 29 | def __init__(self, data): 30 | self.data = data 31 | self.left = None 32 | self.right = None 33 | 34 | 35 | my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4]) 36 | root = create_binary_tree(my_input_list) 37 | print("层序遍历:") 38 | level_order_traversal(root) 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/chapter3/part2/BinaryTreeTraversalStack.py: -------------------------------------------------------------------------------- 1 | class TreeNode: 2 | def __init__(self, data): 3 | self.data = data 4 | self.left = None 5 | self.right = None 6 | 7 | 8 | def create_binary_tree(input_list=[]): 9 | if input_list is None or len(input_list) == 0: 10 | return None 11 | data = input_list.pop(0) 12 | if data is None: 13 | return None 14 | node = TreeNode(data) 15 | node.left = create_binary_tree(input_list) 16 | node.right = create_binary_tree(input_list) 17 | return node 18 | 19 | 20 | def pre_order_traversal_with_stack(node): 21 | stack = [] 22 | while node is not None or len(stack) > 0: 23 | while node is not None: 24 | print(node.data) 25 | stack.append(node) 26 | node = node.left 27 | if len(stack) > 0: 28 | node = stack.pop() 29 | node = node.right 30 | 31 | 32 | my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4]) 33 | root = create_binary_tree(my_input_list) 34 | print("前序遍历:") 35 | pre_order_traversal_with_stack(root) 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/chapter3/part3/HeapOperator.py: -------------------------------------------------------------------------------- 1 | 2 | def up_adjust(array=[]): 3 | """ 4 | 二叉堆的尾节点上浮操作 5 | :param array: 原数组 6 | """ 7 | child_index = len(array) - 1 8 | parent_index = (child_index - 1) // 2 9 | # temp保存插入的叶子节点值,用于最后的赋值 10 | temp = array[child_index] 11 | while child_index > 0 and temp < array[parent_index]: 12 | # 无需真正交换,单向赋值即可 13 | array[child_index] = array[parent_index] 14 | child_index = parent_index 15 | parent_index = (parent_index - 1) // 2 16 | array[child_index] = temp 17 | 18 | 19 | def down_adjust(parent_index, length, array=[]): 20 | """ 21 | 二叉堆的节点下沉操作 22 | :param parent_index: 待下沉的节点下标 23 | :param length: 堆的长度范围 24 | :param array: 原数组 25 | """ 26 | # temp保存父节点值,用于最后的赋值 27 | temp = array[parent_index] 28 | child_index = 2 * parent_index + 1 29 | while child_index < length: 30 | # 如果有右孩子,且右孩子小于左孩子的值,则定位到右孩子 31 | if child_index + 1 < length and array[child_index + 1] < array[child_index]: 32 | child_index += 1 33 | # 如果父节点小于任何一个孩子的值,直接跳出 34 | if temp <= array[child_index]: 35 | break 36 | # 无需真正交换,单向赋值即可 37 | array[parent_index] = array[child_index] 38 | parent_index = child_index 39 | child_index = 2 * child_index + 1 40 | array[parent_index] = temp 41 | 42 | 43 | def build_heap(array=[]): 44 | """ 45 | 二叉堆的构建操作 46 | :param array: 原数组 47 | """ 48 | # 从最后一个非叶子节点开始,依次下沉调整 49 | for i in range((len(array)-2) // 2, -1, -1): 50 | down_adjust(i, len(array), array) 51 | 52 | 53 | my_array = list([1, 3, 2, 6, 5, 7, 8, 9, 10, 0]) 54 | up_adjust(my_array) 55 | print(my_array) 56 | my_array = list([7, 1, 3, 10, 5, 2, 8, 9, 6]) 57 | build_heap(my_array) 58 | print(my_array) 59 | -------------------------------------------------------------------------------- /src/chapter3/part4/PriorityQueue.py: -------------------------------------------------------------------------------- 1 | class PriorityQueue: 2 | 3 | def __init__(self): 4 | self.array = [] 5 | self.size = 0 6 | 7 | def enqueue(self, element): 8 | self.array.append(element) 9 | self.size += 1 10 | self.up_adjust() 11 | 12 | def dequeue(self): 13 | if self.size < 0: 14 | raise Exception("队列为空 !") 15 | head = self.array[0] 16 | self.array[0] = self.array[self.size-1] 17 | self.size -= 1 18 | self.down_adjust() 19 | return head 20 | 21 | def up_adjust(self): 22 | child_index = self.size - 1 23 | parent_index = (child_index - 1) // 2 24 | # temp保存插入的叶子节点值,用于最后的赋值 25 | temp = self.array[child_index] 26 | while child_index > 0 and temp > self.array[parent_index]: 27 | # 无需真正交换,单向赋值即可 28 | self.array[child_index] = self.array[parent_index] 29 | child_index = parent_index 30 | parent_index = (parent_index - 1) // 2 31 | self.array[child_index] = temp 32 | 33 | def down_adjust(self): 34 | parent_index = 0 35 | # temp保存父节点值,用于最后的赋值 36 | temp = self.array[parent_index] 37 | child_index = 1 38 | while child_index < self.size: 39 | # 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子 40 | if child_index + 1 < self.size and self.array[child_index + 1] > self.array[child_index]: 41 | child_index += 1 42 | # 如果父节点大于任何一个孩子的值,直接跳出 43 | if temp >= self.array[child_index]: 44 | break 45 | # 无需真正交换,单向赋值即可 46 | self.array[parent_index] = self.array[child_index] 47 | parent_index = child_index 48 | child_index = 2 * child_index + 1 49 | self.array[parent_index] = temp 50 | 51 | 52 | queue = PriorityQueue() 53 | queue.enqueue(3) 54 | queue.enqueue(5) 55 | queue.enqueue(10) 56 | queue.enqueue(2) 57 | queue.enqueue(7) 58 | print(queue.dequeue()) 59 | print(queue.dequeue()) 60 | 61 | -------------------------------------------------------------------------------- /src/chapter4/part2/BubbleSort.py: -------------------------------------------------------------------------------- 1 | 2 | def bubble_sort_v1(array=[]): 3 | for i in range(len(array)-1): 4 | for j in range(len(array)-i-1): 5 | if array[j] > array[j+1]: 6 | temp = array[j] 7 | array[j] = array[j+1] 8 | array[j+1] = temp 9 | 10 | 11 | def bubble_sort_v2(array=[]): 12 | for i in range(len(array)-1): 13 | # 有序标记,每一轮的初始是true 14 | is_sorted = True 15 | for j in range(len(array)-i-1): 16 | if array[j] > array[j+1]: 17 | temp = array[j] 18 | array[j] = array[j+1] 19 | array[j+1] = temp 20 | # 有元素交换,所以不是有序,标记变为false 21 | is_sorted = False 22 | if is_sorted: 23 | break 24 | 25 | 26 | def bubble_sort_v3(array=[]): 27 | # 记录最后一次交换的位置 28 | last_exchange_index = 0 29 | # 无序数列的边界,每次比较只需要比到这里为止 30 | sort_border = len(array)-1 31 | for i in range(len(array)-1): 32 | # 有序标记,每一轮的初始是true 33 | is_sorted = True 34 | for j in range(sort_border): 35 | if array[j] > array[j+1]: 36 | temp = array[j] 37 | array[j] = array[j+1] 38 | array[j+1] = temp 39 | # 有元素交换,所以不是有序,标记变为false 40 | is_sorted = False 41 | # 把无序数列的边界更新为最后一次交换元素的位置 42 | last_exchange_index = j 43 | sort_border = last_exchange_index 44 | if is_sorted: 45 | break 46 | 47 | 48 | my_array = list([3, 4, 14, 1, 5, 6, 7, 8, 1, -1, 0, 9, 11]) 49 | bubble_sort_v3(my_array) 50 | print(my_array) 51 | 52 | -------------------------------------------------------------------------------- /src/chapter4/part2/CockTailSort.py: -------------------------------------------------------------------------------- 1 | 2 | def cock_tail__sort(array=[]): 3 | for i in range(len(array) // 2): 4 | # 有序标记,每一轮的初始是true 5 | is_sorted = True 6 | # 奇数轮,从左向右比较和交换 7 | for j in range(i, len(array)-i-1): 8 | if array[j] > array[j+1]: 9 | temp = array[j] 10 | array[j] = array[j+1] 11 | array[j+1] = temp 12 | # 有元素交换,所以不是有序,标记变为false 13 | is_sorted = False 14 | if is_sorted: 15 | break 16 | # 偶数轮之前,重新标记为true 17 | is_sorted = True 18 | # 偶数轮,从右向左比较和交换 19 | for j in range(len(array)-i-1, i, -1): 20 | if array[j] < array[j-1]: 21 | temp = array[j] 22 | array[j] = array[j-1] 23 | array[j-1] = temp 24 | # 有元素交换,所以不是有序,标记变为false 25 | is_sorted = False 26 | if is_sorted: 27 | break 28 | 29 | 30 | my_array = list([3, 4, 14, 1, 5, 6, 7, 8, 1, -1, 0, 9, 11]) 31 | cock_tail__sort(my_array) 32 | print(my_array) 33 | 34 | -------------------------------------------------------------------------------- /src/chapter4/part3/QuickSort.py: -------------------------------------------------------------------------------- 1 | 2 | def quick_sort(start_index, end_index, array=[]): 3 | # 递归结束条件:startIndex大等于endIndex的时候 4 | if start_index >= end_index: 5 | return 6 | # 得到基准元素位置 7 | pivot_index = partition_v1(start_index, end_index, array) 8 | # 根据基准元素,分成两部分递归排序 9 | quick_sort(start_index, pivot_index - 1, array) 10 | quick_sort(pivot_index + 1, end_index, array) 11 | 12 | 13 | def partition_v1(start_index, end_index, array=[]): 14 | # 取第一个位置的元素作为基准元素(也可以选择随机位置) 15 | pivot = array[start_index] 16 | left = start_index 17 | right = end_index 18 | while left != right: 19 | # 控制right指针比较并左移 20 | while left < right and array[right] > pivot: 21 | right -= 1 22 | # 控制left指针比较并右移 23 | while left < right and array[left] <= pivot: 24 | left += 1 25 | # 交换left和right指向的元素 26 | if left < right: 27 | p = array[left] 28 | array[left] = array[right] 29 | array[right] = p 30 | # pivot和指针重合点交换 31 | array[start_index] = array[left] 32 | array[left] = pivot 33 | return left 34 | 35 | 36 | def partition_v2(start_index, end_index, array=[]): 37 | # 取第一个位置的元素作为基准元素(也可以选择随机位置) 38 | pivot = array[start_index] 39 | mark = start_index 40 | for i in range(start_index+1, end_index+1): 41 | if array[i] < pivot: 42 | mark += 1 43 | p = array[mark] 44 | array[mark] = array[i] 45 | array[i] = p 46 | array[start_index] = array[mark] 47 | array[mark] = pivot 48 | return mark 49 | 50 | 51 | my_array = list([3, 4, 14, 1, 5, 6, 7, 8, 1, -1, 0, 9, 11]) 52 | quick_sort(0, len(my_array)-1, my_array) 53 | print(my_array) 54 | 55 | -------------------------------------------------------------------------------- /src/chapter4/part3/QuickSortWithStack.py: -------------------------------------------------------------------------------- 1 | 2 | def quick_sort(start_index, end_index, array=[]): 3 | # 用一个集合栈来代替递归的函数栈 4 | quick_sort_stack = [] 5 | # 整个数列的起止下标,以哈希的形式入栈 6 | root_param = {"startIndex": start_index, "endIndex": end_index} 7 | quick_sort_stack.append(root_param) 8 | 9 | # 循环结束条件:栈为空时结束 10 | while len(quick_sort_stack) > 0: 11 | # 栈顶元素出栈,得到起止下标 12 | param = quick_sort_stack.pop() 13 | # 得到基准元素位置 14 | pivot_index = partition(param.get("startIndex"), param.get("endIndex"), array) 15 | # 根据基准元素分成两部分, 把每一部分的起止下标入栈 16 | if param.get("startIndex") < pivot_index - 1: 17 | left_param = {"startIndex": param.get("startIndex"), "endIndex": pivot_index - 1} 18 | quick_sort_stack.append(left_param) 19 | if pivot_index + 1 < param.get("endIndex"): 20 | right_param = {"startIndex": pivot_index + 1, "endIndex": param.get("endIndex")} 21 | quick_sort_stack.append(right_param) 22 | 23 | 24 | def partition(start_index, end_index, array=[]): 25 | # 取第一个位置的元素作为基准元素(也可以选择随机位置) 26 | pivot = array[start_index] 27 | mark = start_index 28 | for i in range(start_index+1, end_index+1): 29 | if array[i] < pivot: 30 | mark += 1 31 | p = array[mark] 32 | array[mark] = array[i] 33 | array[i] = p 34 | array[start_index] = array[mark] 35 | array[mark] = pivot 36 | return mark 37 | 38 | 39 | my_array = list([3, 4, 14, 1, 5, 6, 7, 8, 1, -1, 0, 9, 11]) 40 | quick_sort(0, len(my_array)-1, my_array) 41 | print(my_array) 42 | 43 | -------------------------------------------------------------------------------- /src/chapter4/part4/HeapSort.py: -------------------------------------------------------------------------------- 1 | 2 | def heap_sort(array=[]): 3 | # 1.把无序数组构建成最大堆 4 | for i in range((len(array)-2)//2, -1, -1): 5 | down_adjust(i, len(array), array) 6 | # 2.循环交换集合尾部元素到堆顶,并调节堆产生新的堆顶 7 | for i in range(len(array)-1, 0, -1): 8 | # 最后一个元素和第一元素进行交换 9 | temp = array[i] 10 | array[i] = array[0] 11 | array[0] = temp 12 | # 下沉调整最大堆 13 | down_adjust(0, i, array) 14 | 15 | 16 | def down_adjust(parent_index, length, array=[]): 17 | # temp保存父节点值,用于最后的赋值 18 | temp = array[parent_index] 19 | child_index = 2 * parent_index + 1 20 | while child_index < length: 21 | # 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子 22 | if child_index+1 < length and array[child_index+1] > array[child_index]: 23 | child_index += 1 24 | # 如果父节点大于等于任何一个孩子的值,直接跳出 25 | if temp >= array[child_index]: 26 | break 27 | # 无需真正交换,单向赋值即可 28 | array[parent_index] = array[child_index] 29 | parent_index = child_index 30 | child_index = 2 * child_index + 1 31 | array[parent_index] = temp 32 | 33 | 34 | my_array = list([3, 4, 14, 1, 5, 6, 7, 8, 1, -1, 0, 9, 11]) 35 | heap_sort(my_array) 36 | print(my_array) 37 | 38 | -------------------------------------------------------------------------------- /src/chapter4/part5/BucketSort.py: -------------------------------------------------------------------------------- 1 | 2 | def bucket_sort(array=[]): 3 | # 1.得到数列的最大值最小值,并算出差值d 4 | max_value = array[0] 5 | min_value = array[0] 6 | for i in range(1, len(array)): 7 | if array[i] > max_value: 8 | max_value = array[i] 9 | if array[i] < min_value: 10 | min_value = array[i] 11 | d = max_value - min_value 12 | # 2.初始化桶 13 | bucket_num = len(array) 14 | bucket_list = [] 15 | for i in range(0, bucket_num): 16 | bucket_list.append([]) 17 | # 3.遍历原始数组,将每个元素放入桶中 18 | for i in range(0, len(array)): 19 | num = int((array[i] - min_value) * (bucket_num-1) / d) 20 | bucket = bucket_list[num] 21 | bucket.append(array[i]) 22 | # 4.对每个桶内部进行排序 23 | for i in range(0, len(bucket_list)): 24 | # sort方法采用了时间复杂度O(nlogn)的排序算法 25 | bucket_list[i].sort() 26 | # 5.输出全部元素 27 | sorted_array = [] 28 | for sub_list in bucket_list: 29 | for element in sub_list: 30 | sorted_array.append(element) 31 | return sorted_array 32 | 33 | 34 | my_array = list([4.12, 6.421, 0.0023, 3.0, 2.123, 8.122, 4.12, 10.09]) 35 | print(bucket_sort(my_array)) 36 | 37 | -------------------------------------------------------------------------------- /src/chapter4/part5/CountSort.py: -------------------------------------------------------------------------------- 1 | 2 | def count_sort(array=[]): 3 | # 1.得到数列的最大值 4 | max_value = array[0] 5 | for i in range(1, len(array)): 6 | if array[i] > max_value: 7 | max_value = array[i] 8 | # 2.根据数列最大值确定统计数组的长度 9 | count_array = [0] * (max_value+1) 10 | # 3.遍历数列,填充统计数组 11 | for i in range(0, len(array)): 12 | count_array[array[i]] += 1 13 | # 4.遍历统计数组,输出结果 14 | sorted_array = [] 15 | for i in range(0, len(count_array)): 16 | for j in range(0, count_array[i]): 17 | sorted_array.append(i) 18 | return sorted_array 19 | 20 | 21 | def count_sort_v2(array=[]): 22 | # 1.得到数列的最大值最小值,并算出差值d 23 | max_value = array[0] 24 | min_value = array[0] 25 | for i in range(1, len(array)): 26 | if array[i] > max_value: 27 | max_value = array[i] 28 | if array[i] < min_value: 29 | min_value = array[i] 30 | d = max_value - min_value 31 | # 2.创建统计数组并统计对应元素个数 32 | count_array = [0] * (d+1) 33 | for i in range(0, len(array)): 34 | count_array[array[i]-min_value] += 1 35 | # 3.统计数组做变形,后面的元素等于前面的元素之和 36 | for i in range(1, len(count_array)): 37 | count_array[i] += count_array[i-1] 38 | # 4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组 39 | sorted_array = [0] * len(array) 40 | for i in range(len(array)-1, -1, -1): 41 | sorted_array[count_array[array[i]-min_value]-1] = array[i] 42 | count_array[array[i] - min_value] -= 1 43 | return sorted_array 44 | 45 | 46 | my_array = list([4, 4, 6, 5, 3, 2, 8, 1, 7, 5, 6, 0, 10]) 47 | print(count_sort(my_array)) 48 | my_array = list([95, 94, 91, 120, 90, 99, 93, 91, 92]) 49 | print(count_sort_v2(my_array)) 50 | 51 | -------------------------------------------------------------------------------- /src/chapter5/part10/BigNumberSum.py: -------------------------------------------------------------------------------- 1 | def big_number_sum(big_number_a, big_number_b): 2 | # 把两个大整数用数组逆序存储,数组长度等于较大整数位数 + 1 3 | max_length = len(big_number_a) if len(big_number_a)> len(big_number_b) else len(big_number_b) 4 | big_number_a = big_number_a.zfill(max_length) 5 | big_number_b = big_number_b.zfill(max_length) 6 | array_a = list(big_number_a) 7 | array_b = list(big_number_b) 8 | # 2.构建result数组,数组长度等于较大整数位数 + 1 9 | result = [0] * (max_length + 1) 10 | # 3.遍历数组,按位相加 11 | for i in range(max_length-1, -1, -1): 12 | temp = result[i+1] 13 | temp += int(array_a[i]) 14 | temp += int(array_b[i]) 15 | # 判断是否进位 16 | if temp >= 10: 17 | temp = temp-10 18 | result[i] = 1 19 | result[i+1] = temp 20 | if result[0] == 0: 21 | result.pop(0) 22 | # 4.把result数组转成String 23 | result = [str(i) for i in result] 24 | result_str = "".join(result) 25 | return result_str 26 | 27 | 28 | print(big_number_sum("426709752318", "95481253129")) 29 | 30 | -------------------------------------------------------------------------------- /src/chapter5/part11/GoldMining.py: -------------------------------------------------------------------------------- 1 | def get_best_gold_mining(w, n, p=[], g=[]): 2 | """ 3 | :param w: 工人数量 4 | :param n: 可选金矿数量 5 | :param p: 金矿开采所需工人数量 6 | :param g: 金矿储量 7 | :return: 最优收益 8 | """ 9 | if w == 0 or n == 0: 10 | return 0 11 | if w < p[n-1]: 12 | return get_best_gold_mining(w, n-1, p, g) 13 | return max(get_best_gold_mining(w, n-1, p, g), get_best_gold_mining(w - p[n-1], n-1, p, g) + g[n-1]) 14 | 15 | 16 | def get_best_gold_mining_v2(w, p=[], g=[]): 17 | """ 18 | :param w: 工人数量 19 | :param p: 金矿开采所需工人数量 20 | :param g: 金矿储量 21 | :return: 最优收益 22 | """ 23 | result_table = [[0 for i in range(w+1)] for i in range(len(g)+1)] 24 | # 填充表格 25 | for i in range(1, len(g)+1): 26 | for j in range(1, w+1): 27 | if j < p[i-1]: 28 | result_table[i][j] = result_table[i-1][j] 29 | else: 30 | result_table[i][j] = max(result_table[i-1][j], result_table[i-1][j-p[i-1]]+ g[i-1]) 31 | # 返回最后一个格子的值 32 | return result_table[len(g)][w] 33 | 34 | 35 | def get_best_gold_mining_v3(w, p=[], g=[]): 36 | """ 37 | :param w: 工人数量 38 | :param p: 金矿开采所需工人数量 39 | :param g: 金矿储量 40 | :return: 最优收益 41 | """ 42 | # 创建当前结果 43 | results = [0]*(w+1) 44 | # 填充一维数组 45 | for i in range(1, len(g)+1): 46 | for j in range(w, 0, -1): 47 | if j >= p[i-1]: 48 | results[j] = max(results[j], results[j-p[i-1]] + g[i-1]) 49 | # 返回最后一个格子的值 50 | return results[w] 51 | 52 | 53 | test_w = 10 54 | test_p = list([5, 5, 3, 4, 3]) 55 | test_g = list({400, 500, 200, 300, 350}) 56 | print("最优收益:", get_best_gold_mining_v2(test_w, test_p, test_g)) 57 | 58 | -------------------------------------------------------------------------------- /src/chapter5/part12/MedianSortedArrays.py: -------------------------------------------------------------------------------- 1 | def find_median_sorted_arrays(array_A, array_B): 2 | m, n = len(array_A), len(array_B) 3 | # 如果数组A的长度大于等于数组B,则交换数组 4 | if m > n: 5 | array_A, array_B, m, n = array_B, array_A, n, m 6 | if n == 0: 7 | raise ValueError 8 | start, end, half_len = 0, m, (m + n + 1) // 2 9 | while start <= end: 10 | i = (start + end) // 2 11 | j = half_len - i 12 | if i < m and array_B[j-1] > array_A[i]: 13 | # i偏小了,需要右移 14 | start = i + 1 15 | elif i > 0 and array_A[i - 1] > array_B[j]: 16 | # i偏大了,需要左移 17 | end = i - 1 18 | else: 19 | # i刚好合适,或i已达到数组边界 20 | if i == 0: 21 | max_of_left = array_B[j-1] 22 | elif j == 0: 23 | max_of_left = array_A[i-1] 24 | else: 25 | max_of_left = max(array_A[i-1], array_B[j-1]) 26 | if (m + n) % 2 == 1: 27 | # 如果大数组的长度是奇数,中位数就是左半部分的最大值 28 | return max_of_left 29 | if i == m: 30 | min_of_right = array_B[j] 31 | elif j == n: 32 | min_of_right = array_A[i] 33 | else: 34 | min_of_right = min(array_A[i], array_B[j]) 35 | # 如果大数组的长度是偶数,取左侧最大值和右侧最小值的平均 36 | return (max_of_left + min_of_right) / 2.0 37 | 38 | 39 | my_array_A = list([3, 5, 6, 7, 8, 12, 20]) 40 | my_array_B = list([1, 10, 17, 18]) 41 | print(find_median_sorted_arrays(my_array_A, my_array_B)) 42 | 43 | -------------------------------------------------------------------------------- /src/chapter5/part13/FindLostNum.py: -------------------------------------------------------------------------------- 1 | def find_lost_num(array=[]): 2 | # 用于存储两个出现奇数次的整数 3 | result = [0, 0] 4 | # 第一次整体异或 5 | xor_result = 0 6 | for i in range(0, len(array)): 7 | xor_result ^= array[i] 8 | # 如果异或结果为0,说明输入数组不符合题目 9 | if xor_result == 0: 10 | raise ValueError 11 | # 确定两个整数的不同位,以此来做分组 12 | separator = 1 13 | while 0 == (xor_result & separator): 14 | separator <<= 1 15 | # 第二次分组异或 16 | for i in range(0, len(array)): 17 | if 0 == (array[i] & separator): 18 | result[0] ^= array[i] 19 | else: 20 | result[1] ^= array[i] 21 | return result 22 | 23 | 24 | my_array = list([4, 1, 2, 2, 5, 1, 4, 3]) 25 | print(find_lost_num(my_array)) 26 | 27 | -------------------------------------------------------------------------------- /src/chapter5/part2/LinkedListCycle.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, data): 3 | self.data = data 4 | self.next = None 5 | 6 | 7 | def is_cycle(head): 8 | p1 = head 9 | p2 = head 10 | while p2 is not None and p2.next is not None: 11 | p1 = p1.next 12 | p2 = p2.next.next 13 | if p1 == p2: 14 | return True 15 | return False 16 | 17 | 18 | node1 = Node(5) 19 | node2 = Node(3) 20 | node3 = Node(7) 21 | node4 = Node(2) 22 | node5 = Node(6) 23 | node1.next = node2 24 | node2.next = node3 25 | node3.next = node4 26 | node4.next = node5 27 | node5.next = node2 28 | print(is_cycle(node1)) 29 | 30 | -------------------------------------------------------------------------------- /src/chapter5/part3/MinStack.py: -------------------------------------------------------------------------------- 1 | class MinStack: 2 | def __init__(self): 3 | self.main_stack = [] 4 | self.min_stack = [] 5 | 6 | def push(self, element): 7 | self.main_stack.append(element) 8 | # 如果辅助栈为空,或新元素小于等于辅助栈栈顶,则新元素压入辅助栈 9 | if len(self.min_stack) == 0 or element <= self.min_stack[len(self.min_stack) - 1]: 10 | self.min_stack.append(element) 11 | 12 | def pop(self): 13 | # 如果出栈元素和辅助栈栈顶元素值相等,辅助栈的栈顶元素出栈 14 | if self.main_stack[len(self.main_stack) - 1] == self.min_stack[len(self.min_stack) - 1]: 15 | self.min_stack.pop() 16 | return self.main_stack.pop() 17 | 18 | def get_min(self): 19 | if len(self.main_stack) == 0: 20 | return None 21 | return self.min_stack[len(self.min_stack) - 1] 22 | 23 | 24 | my_stack = MinStack() 25 | my_stack.push(4) 26 | my_stack.push(9) 27 | my_stack.push(7) 28 | my_stack.push(3) 29 | my_stack.push(8) 30 | my_stack.push(5) 31 | print(my_stack.get_min()) 32 | my_stack.pop() 33 | my_stack.pop() 34 | my_stack.pop() 35 | print(my_stack.get_min()) 36 | -------------------------------------------------------------------------------- /src/chapter5/part4/GreatestCommonDivisor.py: -------------------------------------------------------------------------------- 1 | def get_greatest_common_divisor(a, b): 2 | big = max(a, b) 3 | small = min(a, b) 4 | if big % small == 0: 5 | return small 6 | for i in range(small//2, 1, -1): 7 | if small % i == 0 and big % i == 0: 8 | return i 9 | return 1 10 | 11 | 12 | def get_greatest_common_divisor_v2(a, b): 13 | big = max(a, b) 14 | small = min(a, b) 15 | if big % small == 0: 16 | return small 17 | return get_greatest_common_divisor_v2(big % small, small) 18 | 19 | 20 | def get_greatest_common_divisor_v3(a, b): 21 | if a == b: 22 | return a 23 | big = max(a, b) 24 | small = min(a, b) 25 | return get_greatest_common_divisor_v2(big-small, small) 26 | 27 | 28 | def get_greatest_common_divisor_v4(a, b): 29 | if a == b: 30 | return a 31 | if (a & 1) == 0 and (b & 1) == 0: 32 | return get_greatest_common_divisor_v4(a >> 1, b >> 1) << 1 33 | elif (a & 1) == 0 and (b & 1) != 0: 34 | return get_greatest_common_divisor_v4(a >> 1, b) 35 | elif (a & 1) != 0 and (b & 1) == 0: 36 | return get_greatest_common_divisor_v4(a, b >> 1) 37 | else: 38 | big = max(a, b) 39 | small = min(a, b) 40 | return get_greatest_common_divisor_v4(big - small, small) 41 | 42 | 43 | print(get_greatest_common_divisor(25, 5)) 44 | print(get_greatest_common_divisor_v2(100, 75)) 45 | print(get_greatest_common_divisor_v3(99, 55)) 46 | print(get_greatest_common_divisor_v4(100, 80)) 47 | -------------------------------------------------------------------------------- /src/chapter5/part5/PowerOf2.py: -------------------------------------------------------------------------------- 1 | def is_power_of_2(num): 2 | temp = 1 3 | while temp <= num: 4 | if temp == num: 5 | return True 6 | temp = temp * 2 7 | return False 8 | 9 | 10 | def is_power_of_2_v2(num): 11 | temp = 1 12 | while temp <= num: 13 | if temp == num: 14 | return True 15 | temp = temp << 1 16 | return False 17 | 18 | 19 | def is_power_of_2_v3(num): 20 | return (num & num-1) == 0 21 | 22 | 23 | print(is_power_of_2_v3(19)) 24 | print(is_power_of_2_v3(32)) 25 | -------------------------------------------------------------------------------- /src/chapter5/part6/MaxSortedDistance.py: -------------------------------------------------------------------------------- 1 | class Bucket: 2 | def __init__(self): 3 | self.min = None 4 | self.max = None 5 | 6 | 7 | def get_max_sorted_distance(array=[]): 8 | # 1.得到数列的最大值和最小值 9 | max_value = array[0] 10 | min_value = array[0] 11 | for i in range(1, len(array)): 12 | if array[i] > max_value: 13 | max_value = array[i] 14 | if array[i] < min_value: 15 | min_value = array[i] 16 | d = max_value - min_value 17 | # 如果max和min相等,说明数组所有元素都相等,返回0 18 | if d == 0: 19 | return 0 20 | # 2.初始化桶 21 | bucket_num = len(array) 22 | buckets = [] 23 | for i in range(0, bucket_num): 24 | buckets.append(Bucket()) 25 | # 3.遍历原始数组,确定每个桶的最大最小值 26 | for i in range(0, len(array)): 27 | # 确定数组元素所归属的桶下标 28 | index = int((array[i] - min_value) * (bucket_num-1) / d) 29 | if buckets[index].min is None or buckets[index].min > array[i]: 30 | buckets[index].min = array[i] 31 | if buckets[index].max is None or buckets[index].max < array[i]: 32 | buckets[index].max = array[i] 33 | # 4.遍历桶,找到最大差值 34 | left_max = buckets[0].max 35 | max_distance = 0 36 | for i in range(1, len(buckets)): 37 | if buckets[i].min is None: 38 | continue 39 | if buckets[i].min - left_max > max_distance: 40 | max_distance = buckets[i].min - left_max 41 | left_max = buckets[i].max 42 | return max_distance 43 | 44 | 45 | my_array = list([2, 6, 3, 4, 5, 10, 9]) 46 | print(get_max_sorted_distance(my_array)) 47 | -------------------------------------------------------------------------------- /src/chapter5/part7/StackQueue.py: -------------------------------------------------------------------------------- 1 | class StackQueue: 2 | def __init__(self): 3 | self.stackA = [] 4 | self.stackB = [] 5 | 6 | def en_queue(self, element): 7 | self.stackA.append(element) 8 | 9 | def de_queue(self): 10 | if len(self.stackB) == 0: 11 | if len(self.stackA) == 0: 12 | raise Exception("栈已经空了 !") 13 | self.transfer() 14 | return self.stackB.pop() 15 | 16 | def transfer(self): 17 | while len(self.stackA) > 0: 18 | self.stackB.append(self.stackA.pop()) 19 | 20 | 21 | stack_queue = StackQueue() 22 | stack_queue.en_queue(1) 23 | stack_queue.en_queue(2) 24 | stack_queue.en_queue(3) 25 | print(stack_queue.de_queue()) 26 | print(stack_queue.de_queue()) 27 | stack_queue.en_queue(4) 28 | print(stack_queue.de_queue()) 29 | print(stack_queue.de_queue()) 30 | 31 | -------------------------------------------------------------------------------- /src/chapter5/part8/FindNearestNumber.py: -------------------------------------------------------------------------------- 1 | def find_nearest_number(numbers=[]): 2 | # 1.从后向前查看逆序区域,找到逆序区域的前一位,也就是数字置换的边界 3 | index = find_transfer_point(numbers) 4 | # 如果数字置换边界是0,说明整个数组已经逆序,无法得到更大的相同数字组成的整数,返回null 5 | if index == 0: 6 | return None 7 | # 2.把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置 8 | # 拷贝入参,避免直接修改入参 9 | numbers_copy = numbers.copy() 10 | exchange_head(index, numbers_copy) 11 | # 3.把原来的逆序区域转为顺序 12 | reverse(index, numbers_copy) 13 | return numbers_copy 14 | 15 | 16 | def find_transfer_point(numbers=[]): 17 | for i in range(len(numbers)-1, 0, -1): 18 | if numbers[i] > numbers[i-1]: 19 | return i 20 | return 0 21 | 22 | 23 | def exchange_head(index, numbers=[]): 24 | head = numbers[index-1] 25 | for i in range(len(numbers)-1, 0, -1): 26 | if head < numbers[i]: 27 | numbers[index-1] = numbers[i] 28 | numbers[i] = head 29 | break 30 | return numbers 31 | 32 | 33 | def reverse(index, numbers=[]): 34 | i = index 35 | j = len(numbers)-1 36 | while i < j: 37 | temp = numbers[i] 38 | numbers[i] = numbers[j] 39 | numbers[j] = temp 40 | i += 1 41 | j -= 1 42 | return numbers 43 | 44 | 45 | def output_numbers(numbers=[]): 46 | for i in numbers: 47 | print(i, end='') 48 | print() 49 | 50 | 51 | my_numbers = list([1, 2, 3, 4, 5]) 52 | # 打印12345之后的10个全排列整数 53 | for k in range(0, 10): 54 | my_numbers = find_nearest_number(my_numbers) 55 | output_numbers(my_numbers) 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/chapter5/part9/RemoveKDigits.py: -------------------------------------------------------------------------------- 1 | def remove_k_digits(num, k): 2 | for i in range(0, k): 3 | has_cut = False 4 | # 从左向右遍历,找到比自己右侧数字大的数字并删除 5 | for j in range(0, len(num)-1): 6 | if num[j] > num[j+1]: 7 | num = num[0:j]+num[j+1:len(num)] 8 | has_cut = True 9 | break 10 | # 如果没有找到要删除的数字,则删除最后一个数字 11 | if not has_cut: 12 | num = num[0:len(num)-1] 13 | # 清除整数左侧的数字0 14 | start = 0 15 | for j in range(0, len(num)-1): 16 | if num[j] != '0': 17 | break 18 | start += 1 19 | num = num[start:len(num)] 20 | # 如果整数的所有数字都被删除了,直接返回0 21 | if len(num) == 0: 22 | return "0" 23 | return num 24 | 25 | 26 | def remove_k_digits_v2(num, k): 27 | # 新整数的最终长度 = 原整数长度 - k 28 | new_length = len(num) - k 29 | # 创建一个栈,用于接收所有的数字 30 | stack = [] 31 | for i in range(0, len(num)): 32 | # 遍历当前数字 33 | c = num[i] 34 | # 当栈顶数字大于遍历到的当前数字,栈顶数字出栈(相当于删除数字) 35 | while len(stack) > 0 and stack[len(stack)-1] > c and k > 0: 36 | stack.pop() 37 | k -= 1 38 | # 如果遇到数字0,且栈为空,0不入栈 39 | if '0' == c and len(stack) == 0: 40 | new_length -= 1 41 | if new_length <= 0: 42 | return "0" 43 | continue 44 | # 遍历到的当前数字入栈 45 | stack.append(c) 46 | # 用栈构建新的整数字符串 47 | return "".join(stack[:new_length]) 48 | 49 | 50 | print(remove_k_digits_v2("123456789", 3)) 51 | print(remove_k_digits_v2("30200", 1)) 52 | print(remove_k_digits_v2("10", 2)) 53 | print(remove_k_digits_v2("541270936", 3)) 54 | print(remove_k_digits_v2("1593212", 4)) 55 | print(remove_k_digits_v2("10000100002", 2)) 56 | -------------------------------------------------------------------------------- /src/chapter6/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bjweimengshu/ProgrammerXiaohuiPython/c773d041402115bff61790ed0c4be2fd36193359/src/chapter6/__init__.py -------------------------------------------------------------------------------- /src/chapter6/part2/MyBitmap.py: -------------------------------------------------------------------------------- 1 | class MyBitmap: 2 | def __init__(self, size): 3 | self.words = [0] * (self.get_word_index(size-1) + 1) 4 | self.size = size 5 | 6 | def get_bit(self, bit_index): 7 | if bit_index < 0 or bit_index > self.size-1: 8 | raise Exception("超过bitmap有效范围 !") 9 | word_index = self.get_word_index(bit_index) 10 | return (self.words[word_index] & (1 << bit_index)) != 0 11 | 12 | def set_bit(self, bit_index): 13 | if bit_index < 0 or bit_index > self.size-1: 14 | raise Exception("超过bitmap有效范围 !") 15 | word_index = self.get_word_index(bit_index) 16 | self.words[word_index] |= (1 << bit_index) 17 | 18 | def get_word_index(self, bit_index): 19 | # 右移6位,相当于除以64 20 | return bit_index >> 6 21 | 22 | 23 | bitMap = MyBitmap(21474836470) 24 | bitMap.set_bit(78) 25 | bitMap.set_bit(50) 26 | print(bitMap.get_bit(126)) 27 | print(bitMap.get_bit(78)) 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/chapter6/part3/LRUCache.py: -------------------------------------------------------------------------------- 1 | class LRUCache: 2 | def __init__(self, limit): 3 | self.limit = limit 4 | self.hash = {} 5 | self.head = None 6 | self.end = None 7 | 8 | def get(self, key): 9 | node = self.hash.get(key) 10 | if node is None: 11 | return None 12 | self.refresh_node(node) 13 | return node.value 14 | 15 | def put(self, key, value): 16 | node = self.hash.get(key) 17 | if node is None: 18 | # 如果key不存在,插入key-value 19 | if len(self.hash) >= self.limit: 20 | old_key = self.remove_node(self.head) 21 | self.hash.pop(old_key) 22 | node = Node(key, value) 23 | self.add_node(node) 24 | self.hash[key] = node 25 | else: 26 | # 如果key存在,刷新key-value 27 | node.value = value 28 | self.refresh_node(node) 29 | 30 | def remove(self, key): 31 | node = self.hash.get(key) 32 | if node is None: 33 | return 34 | self.remove_node(node) 35 | self.hash.remove(key) 36 | 37 | def refresh_node(self, node): 38 | # 如果访问的是尾节点,无需移动节点 39 | if node == self.end: 40 | return 41 | # 移除节点 42 | self.remove_node(node) 43 | # 重新插入节点 44 | self.add_node(node) 45 | 46 | def remove_node(self, node): 47 | if node == self.head and node == self.end: 48 | # 移除唯一的节点 49 | self.head = None 50 | self.end = None 51 | elif node == self.end: 52 | # 移除节点 53 | self.end = self.end.pre 54 | self.end.next = None 55 | elif node == self.head: 56 | # 移除头节点 57 | self.head = self.head.next 58 | self.head.pre = None 59 | else: 60 | # 移除中间节点 61 | node.pre.next = node.pre 62 | node.next.pre = node.pre 63 | return node.key 64 | 65 | def add_node(self, node): 66 | if self.end is not None: 67 | self.end.next = node 68 | node.pre = self.end 69 | node.next = None 70 | self.end = node 71 | if self.head is None: 72 | self.head = node 73 | 74 | 75 | class Node: 76 | def __init__(self, key, value): 77 | self.key = key 78 | self.value = value 79 | self.pre = None 80 | self.next = None 81 | 82 | 83 | lruCache = LRUCache(5) 84 | lruCache.put("001", "用户1信息") 85 | lruCache.put("002", "用户2信息") 86 | lruCache.put("003", "用户3信息") 87 | lruCache.put("004", "用户4信息") 88 | lruCache.put("005", "用户5信息") 89 | print(lruCache.get("002")) 90 | lruCache.put("004", "用户4信息更新") 91 | lruCache.put("006", "用户6信息") 92 | print(lruCache.get("001")) 93 | print(lruCache.get("006")) 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/chapter6/part4/AStar.py: -------------------------------------------------------------------------------- 1 | def a_star_search(start, end): 2 | # 待访问的格子 3 | open_list = [] 4 | # 已访问的格子 5 | close_list = [] 6 | # 把起点加入open_list 7 | open_list.append(start) 8 | # 主循环,每一轮检查一个当前方格节点 9 | while len(open_list) > 0: 10 | # 在open_list中查找 F值最小的节点作为当前方格节点 11 | current_grid = find_min_gird(open_list) 12 | # 当前方格节点从openList中移除 13 | open_list.remove(current_grid) 14 | # 当前方格节点进入 closeList 15 | close_list.append(current_grid) 16 | # 找到所有邻近节点 17 | neighbors = find_neighbors(current_grid, open_list, close_list) 18 | for grid in neighbors: 19 | # 邻近节点不在openList中,标记父亲、G、H、F,并放入openList 20 | grid.init_grid(current_grid, end) 21 | open_list.append(grid) 22 | # 如果终点在openList中,直接返回终点格子 23 | for grid in open_list: 24 | if (grid.x == end.x) and (grid.y == end.y): 25 | return grid 26 | # openList用尽,仍然找不到终点,说明终点不可到达,返回空 27 | return None 28 | 29 | 30 | def find_min_gird(open_list=[]): 31 | temp_grid = open_list[0] 32 | for grid in open_list: 33 | if grid.f < temp_grid.f: 34 | temp_grid = grid 35 | return temp_grid 36 | 37 | 38 | def find_neighbors(grid, open_list=[], close_list=[]): 39 | grid_list = [] 40 | if is_valid_grid(grid.x, grid.y-1, open_list, close_list): 41 | grid_list.append(Grid(grid.x, grid.y-1)) 42 | if is_valid_grid(grid.x, grid.y+1, open_list, close_list): 43 | grid_list.append(Grid(grid.x, grid.y+1)) 44 | if is_valid_grid(grid.x-1, grid.y, open_list, close_list): 45 | grid_list.append(Grid(grid.x-1, grid.y)) 46 | if is_valid_grid(grid.x+1, grid.y, open_list, close_list): 47 | grid_list.append(Grid(grid.x+1, grid.y)) 48 | return grid_list 49 | 50 | 51 | def is_valid_grid(x, y, open_list=[], close_list=[]): 52 | # 是否超过边界 53 | if x < 0 or x >= len(MAZE) or y < 0 or y >= len(MAZE[0]): 54 | return False 55 | # 是否有障碍物 56 | if MAZE[x][y] == 1: 57 | return False 58 | # 是否已经在open_list中 59 | if contain_grid(open_list, x, y): 60 | return False 61 | # 是否已经在closeList中 62 | if contain_grid(close_list, x, y): 63 | return False 64 | return True 65 | 66 | 67 | def contain_grid(grids, x, y): 68 | for grid in grids: 69 | if (grid.x == x) and (grid.y == y): 70 | return True 71 | return False 72 | 73 | 74 | class Grid: 75 | def __init__(self, x, y): 76 | self.x = x 77 | self.y = y 78 | self.f = 0 79 | self.g = 0 80 | self.h = 0 81 | self.parent = None 82 | 83 | def init_grid(self, parent, end): 84 | self.parent = parent 85 | self.g = parent.g + 1 86 | self.h = abs(self.x - end.x) + abs(self.y - end.y) 87 | self.f = self.g + self.h 88 | 89 | 90 | # 迷宫地图 91 | MAZE = [ 92 | [0, 0, 0, 0, 0, 0, 0], 93 | [0, 0, 0, 1, 0, 0, 0], 94 | [0, 0, 0, 1, 0, 0, 0], 95 | [0, 0, 0, 1, 0, 0, 0], 96 | [0, 0, 0, 0, 0, 0, 0] 97 | ] 98 | 99 | # 设置起点和终点 100 | start_grid = Grid(2, 1) 101 | end_grid = Grid(2, 5) 102 | # 搜索迷宫终点 103 | result_grid = a_star_search(start_grid, end_grid) 104 | # 回溯迷宫路径 105 | path = [] 106 | while result_grid is not None: 107 | path.append(Grid(result_grid.x, result_grid.y)) 108 | result_grid = result_grid.parent 109 | # 输出迷宫和路径,路径用星号表示 110 | for i in range(0, len(MAZE)): 111 | for j in range(0, len(MAZE[0])): 112 | if contain_grid(path, i, j): 113 | print("*, ", end='') 114 | else: 115 | print(str(MAZE[i][j]) + ", ", end='') 116 | print() 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/chapter6/part5/Redpackage.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | def divide_red_package(total_amount, total_people_num): 5 | amount_list = [] 6 | rest_amount = total_amount 7 | rest_people_num = total_people_num 8 | for i in range(0, total_people_num-1): 9 | # 随机范围:[1,剩余人均金额的两倍),左闭右开 10 | amount = random.randint(1, int(rest_amount/rest_people_num*2)-1) 11 | rest_amount -= amount 12 | rest_people_num -= 1 13 | amount_list.append(amount) 14 | amount_list.append(rest_amount) 15 | return amount_list 16 | 17 | 18 | my_amount_list = divide_red_package(1000, 10) 19 | for my_amount in my_amount_list: 20 | print("抢到金额:%.2f" % (my_amount/100)) 21 | --------------------------------------------------------------------------------