python数据结构与算法知识点_Python知识点整理(2) —— 数据结构与内置算法

数据结构与算法

内置的算法数据结构

数据结构/算法语言内置内置库线性结构list/tuplearray/collections.nametuple链式结构collections.deque(双端队列)字典结构dictcollections.Counter(计数器)/orderedDict(有序字典)集合结构set/frozenset排序算法sorted二分算法bisect模块堆算法heapq模块缓存算法functools.lru_cache(Least Recent Used, python3)

collections模块

namedtuple()deque 提供了一个双端队列CounterOrderedDict(记录key插入的顺序 ,使用了循环双链表实现 )defaultdict

python dict 底层结构

哈希表时间复杂度 o(1)使用二次探查解决哈希冲突问题

哈希冲突

链接法探查法

哈希表扩容

python list/tuple区别

都是线性结构list可变对象,tuple保存的引用不可变(指的是没法替换掉这个对象,但如果引用指向的是可变对象,是可以修改这个引用指向的可变对象的)list没法作为字典的key,tuple可以(可变对象不可hash)

LRU cache

Least Recently Used替换掉最近最少使用的对象当缓存空间不够的时候需要一种方式剔除key常见的有LRU, LFU等LRU通过使用一个循环双端队列不断把最新访问的key放到表头实现

实现LRU Cache

dict + collections.OrderedDict实现dict来当作k/v键值对的缓存orderdict用来实现更新最近访问的key

常考算法

排序算法最差时间分析平均时间复杂度稳定性空间复杂度冒泡排序O(N^2)O(N^2)稳定O(1)选择排序O(N^2)O(N^2)不稳定O(1)插入排序O(N^2)O(N^2)稳定O(1)快速排序O(N^2)O(Nlog2N)不稳定O(log2N) ~O(N)堆排序O(N^log2N)O(Nlog2N)不稳定O(1)

排序算法的稳定性

相同大小的元素排序之后依然保持相对位置不变,就是稳定的

快速排序

退化????分治法(devide and conquer)

def QuickSort(array):

if len(array) <= 1: # 递归出口

return array

pivot_index = 0 # 选择第一个元素作为主元

pivot = array[pivot_index]

pivot_left = [

i for i in array[pivot_index+1:] if array[i]<=pivot

]

pivot_right = [

i for i in array[pivot_index+1:] if array[i] > pivot

]

return QuickSort(pivot_left) + [pivot] + QuickSort(pivot_right)

归并排序

def MergeSortedList(sorted_a, sorted_b):

len_a, len_b = len(sorted_a), len(sorted_b)

a, b = 0, 0

merge_list = []

while a < len_a and b < len_b:

if sorted_a[a] <= sorted_b[b]:

merge_list.append(sorted_a[a])

a += 1

else:

merge_list.append(sorted_b[b])

b += 1

# 把多余的放到有序数组里面

if a < len_a:

merge_list.extend(sorted_a[a:])

else:

merge_list.extend(sorted_b[b:])

return merge_list

def MergeSort(array):

# 定义递归出口

if len(array) <= 1:

return array

mid = len(array) / 2

left_array = MergeSort(array[:mid])

right_array = MergeSort(array[mid:])

return MergeSortedList(left_array, right_array)

堆排序

借助heapq模块快速实现

def HeapSort(array):

from heapq import heappush, heappop

items = []

for val in array:

heappush(items, val)

return [heappop(items) for i in range(len(array))]

二分查找

需要注意边界情况的判定

def BinarySearch(sorted_array, target):

if not sorted_array:

return -1

begin, end = 0, len(sorted_array)-1

while begin <= end:

mid = (begin + end) / 2

if sorted_array[mid] == target:

return mid

if sorted_array[mid] < target: # 要去右边找

begin = mid + 1

else: # 要去左边找

end = mid - 1

return -1

常考数据结构

链表 删除一个节点 合并两个有序链表

队列

collection.deque双端队列 (左右边都可以)

from collections import deque

class Queue:

def __init__(self):

self.itmes = deque()

def append(self, val):

return self.itmes.append(val)

def pop(self):

return self.items.popleft()

def empty(self):

return len(self.items) == 0

用list实现

后面加方便前面,效率不如deque

collections.deque实现用list实现 用栈实现队列 使用栈实现队列的下列操作:

push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。

用一个栈没法实现 先进先出 的结构,用两个栈 实现

push:加到stack1中pop:如果stack2不为空,就直接从stack2中pop出来;如果stack2为空,将当前stack1中的所有pop出来,按照pop的顺序push到stack2中,将stack2中最后添加到元素pop出来。

from collections import deque

class MyStack(object):

"""用deque实现栈"""

def __init__(self):

self.items = deque()

def push(self, x):

return self.itmes.append(x)

def pop(self):

return self.items.pop()

def empty(self):

return len(self.items) == 0

def top(self):

return self.items[-1]

class MyQueue(object):

"""用栈实现队列"""

def __init__(self):

self.s1 = MyStack()

self.s1 = MyStack()

def push(self, x):

self.s1.push()

def pop(self):

if not self.s2.empty():

return self.s2.pop()

while not s1.empty():

val = self.s1.pop()

self.s2.push(val)

return self.s2.pop()

def peek(self):

if not self.s2.empty():

return self.s2.top()

while not s1.empty():

val = self.s1.pop()

self.s2.push(val)

return self.s2.top()

def empty(self):

return self.s1.empty() and self.s2.empty()

用两个栈实现一个队列 min stack

字典&集合

底层:哈希表哈希函数快速定位一个元素不断加入元素会引起哈希表重新开辟空间,拷贝元素到新数组

哈希表解决冲突

链接法:key冲突以后使用链表填充相同的key元素开放寻址法: 冲突后根据一种方式(二次探查)寻找下一个客用的槽

二叉树

先序:根、左、右中序:左、根、右后序:左、右、根二叉树涉及到递归和指针的操作定义一个二叉树:

class TreeNode:

def __init__(self, val, left, right):

self.val, self.left, self.right = val, left, right

二叉树常见题型

二叉树的镜像(翻转二叉树)

递归的方法

def InvertTree(root):

if root:

root.left, root.right = root.right, root.left

InvertTree(root.left)

InvertTree(root.right)

return root

层序遍历二叉树(广度优先)

def levelOrder(self, root):

if not root: # 注意:输入可能为空

return []

res = []

cur_nodes = [root]

next_nodes = []

res.append([i.val for i in cur_nodes])

# 当前、孩子节点不为空

while cur_nodes or next_nodes:

for node in cur_nodes:

if node.left:

next_nodes.append(node.left)

if node.right:

next_nodes.append(node.right)

if next_nodes:

res.append(

[i.val for i in next_nodes]

)

cur_nodes = next_nodes

return res

右视图 (先加右孩子,再加左孩子)

class Solution(object):

def rightSideView(self, root):

if not root: # root == None

return []

res = []

cur_nodes = [root]

next_nodes = []

res.append(cur_nodes[0].val)

while cur_nodes or next_nodes:

for node in cur_nodes:

if node.right:

next_nodes.append(node.right)

if node.left:

next_nodes.append(node.left)

if next_nodes:

res.append(next_nodes[0].val)

cur_nodes = next_nodes

next_nodes = []

return res

二叉树遍历

class BinTreeNode(object):

def __init__(self, data, left=None, right=None):

self.data, self.left, self.right = data, left, right

class BinTree(object):

def __init__(self, root=None):

self.root = root

def preorder_trav(self, subtree):

"""先序遍历"""

if subtree is not None:

print (subtree.data) # 根

self.preorder_trav(subtree.left) # 左子树

self.preorder_trav(subtree.right) # 右子树

def inorder_trav(self, subtree):

"""中序遍历"""

if subtree is not None:

self.inorder_trav(subtree.left) # 左子树

print (subtree.data) # 根

self.inorder_trav(subtree.right) # 右子树

完全二叉树

最大堆:非叶子结点v,v的值都比他的两个孩子大(支持pop获取最大元素)最小堆:非叶子结 点v,v的值都比他的两个孩子小(支持pop获取最小元素) 常见问题

topK问题(找出最大的k个)merge K list

思路1: 第一个和第二个合并,第二个和第三个合并, …思路2: 读取链表里面的值,构造最小堆,最后pop

import heapq

class TopK:

"""

获取最大的k个元素,应该用最小堆实现

思路:

1. 原始数组的前k个元素构成一个最小堆

2. 从第k+1个元素开始:

如果当前元素的值<=堆根节点的值(当前堆中的最小值),pass

如果大于的话,就用这个元素的来代替当前的根节点,并调整堆

"""

def __init__(self, iterable, k):

self.minheap = []

self.capacity = k

self.iterable = iterable

def push(self, val):

if len(self.minheap)>= self.capacity:

min_val = self.minheap[0]

if val < min_val:

pass

else:

heapq.heapreplace(self.minheap, val)

else:

heapq.heappush(self.minheap, val)

def get_topk(self):

for val in self.iteralbe:

self.push(val)

return self.minheap

from heapq import heappush, heappop

class Solution(object):

def mergeKLists(self, lists):

"""

利用堆来合并k个链表

"""

minheap = []

# 遍历,构造堆

for node in lists:

while node:

heappush(minheap, node.val)

node = node.next

if not minheap:# 一定要考虑特殊的输入:[]和[[]]

return None

# 构造有序链表

root = ListNode(heappop(minheap))

cur_node = root

while minheap:

next_node = ListNode(heappop(minheap))

cur_node.next = next_node

cur_node = next_node

return root

字符串常考算法题

常用操作

内置的:split,upper,replace常考题目

翻转字符串 s.reversed()回文字符串

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值