串这一章,主要是讲的串的匹配(主串里面找子串),暴力匹配的方法是子串在主串中按照顺序一个个的匹配,主串的游标首先是0,再是1.....遇到不匹配的地方就回溯,回到1,子串的游标回到0,然后再继续前面匹配的步骤,这样的方法很简单,但是时间复杂度会非常大。
而KMP算法以及其改进的算法,避免了主串游标的回溯,而是只变化子串的位置,降低了时间复杂度,但是KMP步骤真的好难理解啊!书上讲的蛮混乱的,我都没有怎么看懂,所幸找到了一个讲得非常好的博主的讲解:
https://blog.csdn.net/v_july_v/article/details/7041827
写的非常好~清楚明了!
首先要知道的就是二叉树的定义及其三种类型。
定义:一个树,它的孩子节点至多只有两个。
三种类型:
完全二叉树(除了最后一层,其它层节点是满的,并且所有节点都尽可能的靠近左子树)
平衡二叉树(左右子树的深度差距不超过1)
二叉搜索树(左节点的值永远大于右节点)
用python实现:
class binary_tree:
def __init__(self,value):
self.value = value
self.left = None
self.right = None
对于二叉树常见的操作有与递归结合,进行遍历、计算二叉树高度,节点个数等,还有按层打印二叉树。
遍历有三种,先根遍历,中序遍历,后根遍历。实现使用递归非常简单。
先根遍历:先根节点,再左节点,再右节点。
中序遍历:先左,后根,再右。
后根遍历:先右,再左,再根。
def pre(root):
res = []
bianli(root,res)
return res
def bianli(root,res):
if not root:
return -1
res.append(root.value)#中根和后根遍历就是把这句话与后面两句话的顺序进行变化即可
bianli(root.left,res)
bianli(root.right,res)
时间复杂度为:o(n)
二叉树在面试中是最适合于与递归相结合的,除了遍历,还有计算树的高度,计算节点的个数。
计算树的高度:
思路:递归就是一直调用自己函数本身,直到有一个出口,这个出口叫做base case,从这个出口返回到上一步。所以做递归的时候要想清楚的东西是:
出口:在这里的出口就是节点的左右节点都为None时开始返回到上一个节点。
返回的值:在这里返回的是树的高度,如果一个节点的左右节点都没有了,那么这个节点构成的高度为1,如果它有左右节点,那么这个节点构成的高度为左右节点最深的深度加上自身的一层,所以返回的应该是max(left,right)+ 1。
def getHeight(root):
if root == None:
return 0
left = getHeight(root.left)
right = getHeight(root.right)
return max(left,right)+1
时间复杂度o(n)
计算树节点的个数:思路类似
def getNumber(root):
if root == None:
return 0
left = getNumber(root.left)
right = getNumber(root.right)
return left + right + 1
递归其实对于我个人来说真的非常难.....二叉树和递归结合的题每隔一段时间我都得拿出来复习,不然记不住啊,脑子笨呜呜呜呜呜。
计算树的每个左节点节点个数:
在这个定义二叉树节点的时候就加入需要求取的选项。
class binary_tree: def __init__(self,value): self.value = value self.left = None self.right = None self.left_node = 0 #保存左节点数量
def get_left_node_number(root): if root == None: return 0 left = get_left_node_number(root.left) right = get_left_node_number(root.right) root.left_node = left return 1+left+right
计算左右节点之间最深的差距:
class get_max_diff: def result(self): self.maxs = -1 def get(self,root): if root == None: return 0 left = self.get(root.left) right = self.get(root.right) if abs(left-right) > root.maxs: root.maxs = abs(left-right) return 1+left+right
上述几个问题base case都是root为None。如果返回的结果和叶子节点有关系的话,选择的base case就应该变成root的left和right为None。
比如找出二叉树节点最浅的深度是多少这个问题,应该找的是每个节点的叶子结点,这个叶子结点没有任何后继节点。
def get_miniunm(root): if root == None: return 0 if root.left == None and root.right == None: return 1 left = get_miniunm(root.left) if root.left else float('inf') right = get_miniunm(root.right) if root.right else float('inf') return min(left,right)+1
按层打印二叉树:
把二叉树的节点一层层的打印出来:
思路:使用两个队列来实现,一个队列存储当前节点,一个队列储存当前节点的左右节点。再利用一个数组来存储目前层的节点数值。
python实现如下:
def print_tree(root):
if root == None:
return 0
q = [root]#存储当前节点
next = []#存储当前节点的左右节点
val = []#存储当前层所有节点的数值
while q:
head = q.pop(0)
if head.left:
next.append(head.left)
if head.right:
next.append(head.right)
val.append(head.value)
if not q:
print(val)
if next:
q = next
val = []
next = []
除了这些问题之外还有寻找最小公共祖先之类的代码练习题目,我都在力扣网上练习的就不一一放出来啦~
哈夫曼树就是带权路径长度(wpl)最小的二叉树叫做哈弗曼树。
构成方法很简单,书p205。
书上还讲了森林和树之间的变化,我粗略的看了一下~树这一单元中,还是觉得二叉树最最最重要啦!