二分
二分查找只能用有序顺序表:折半查找
一些小问题:len(nums)=n 是n个数,从一开始,而下标是从0开始 因此最后一个下标为n-1
二分(非递归方式)(递归方式)
set函数去除重复值
sort()排序顺序排序
二分查找非递归:用双指针
例1.二分查找非递归
查找两个数的交级应该是这题dd
class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
res=[]
nums1.sort()
nums2.sort()
i ,j =0,0
while i<len(nums1)and j<len(nums2):
if nums1[i]<nums2[j]:
i +=1
elif nums1[i]> nums2[j]:
j+=1
else:
res.append(nums1[i])
i+=1
j+=1
return res
class Solution:
def missingNumber(self, nums: List[int]) -> int:
nums.sort()
i = len(nums)
for j in range(len(nums)):
if j != nums[j]:
return j
else:
i != nums[j]
return i
class Solution:
def missingNumber(self, nums: List[int]) -> int:
i = len(nums)
j = (0+i)*(i+1)//2
a = j -sum(nums)
return a
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
res =[]
for i in nums1:
if i in nums2 and i not in res:
res.append(i)
return res
class Solution:
def search(self, nums: List[int], target: int) -> int:
res=[]
for i in range(len(nums)):
if target == nums[i]:
res.append(i)
return i
if target not in nums:
return -1
二分查找时间复杂度 2^x=n
O(logn)
二叉树
树:类似表格
定义:每个节点有零个或多个子树
没有父节点的节点称为根节点
每一个非根节点有且只有一个父节点
除了根节点,每个子节点可以分为多个不相交的子树
树的术语
节点的度:一个节点含有的子树个数
树的度:那个节点的度最大,就是树的度
叶子节点或终端节点:没有子节点的
父节点:一个节点含有子节点,那么这个子节点的父节点,就是这个节点
兄弟节点:相同父节点的子节点
节点的层次:从根开始为一,根的子节点为2
树的高度:
树的种类:
- 无序树
- 有序树
- 二叉树:每个节点最多含有两个子树
- 完全二叉树:除了最下层的度没达到二个节点,其他层都达到了两个节点
- 满二叉树:所有层都达到了2
- 平衡二叉树:任何节点两个子树的高度差不大于1
- 排序二叉树:就是若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
- 二叉树:每个节点最多含有两个子树
树的存储
- 顺序存储:此存储方式占空间较大
- 链式存储:
常见的一些树的应用场景
xml,html
路由协议
mysql
二叉树的性质
- 在二叉树的i层至多有2^(i-1)
- 深度为k的二叉树最多有2^k-1节点
遍历
二叉树的实现
广度遍历
深度遍历
- 先序遍历 根左右
- 中序遍历 左根右
- 后序遍历 左右根
- 树的构造
- 递归实现先序遍历、中序遍历、后序遍历
- 堆栈实现先序遍历、中序遍历、后序遍历
- 队列实现层次遍历
#coding=utf-8
class Node(object):
"""节点类"""
def __init__(self, elem=-1, lchild=None, rchild=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild
class Tree(object):
"""树类"""
def __init__(self):
self.root = Node()
self.myQueue = []
def add(self, elem):
"""为树添加节点"""
node = Node(elem)
if self.root.elem == -1: # 如果树是空的,则对根节点赋值
self.root = node
self.myQueue.append(self.root)
else:
treeNode = self.myQueue[0] # 此结点的子树还没有齐。
if treeNode.lchild == None:
treeNode.lchild = node
self.myQueue.append(treeNode.lchild)
else:
treeNode.rchild = node
self.myQueue.append(treeNode.rchild)
self.myQueue.pop(0) # 如果该结点存在右子树,将此结点丢弃。
def front_digui(self, root):
"""利用递归实现树的先序遍历"""
if root == None:
return
print root.elem,
self.front_digui(root.lchild)
self.front_digui(root.rchild)
def middle_digui(self, root):
"""利用递归实现树的中序遍历"""
if root == None:
return
self.middle_digui(root.lchild)
print root.elem,
self.middle_digui(root.rchild)
def later_digui(self, root):
"""利用递归实现树的后序遍历"""
if root == None:
return
self.later_digui(root.lchild)
self.later_digui(root.rchild)
print root.elem,
def front_stack(self, root):
"""利用堆栈实现树的先序遍历"""
if root == None:
return
myStack = []
node = root
while node or myStack:
while node: #从根节点开始,一直找它的左子树
print node.elem,
myStack.append(node)
node = node.lchild
node = myStack.pop() #while结束表示当前节点node为空,即前一个节点没有左子树了
node = node.rchild #开始查看它的右子树
def middle_stack(self, root):
"""利用堆栈实现树的中序遍历"""
if root == None:
return
myStack = []
node = root
while node or myStack:
while node: #从根节点开始,一直找它的左子树
myStack.append(node)
node = node.lchild
node = myStack.pop() #while结束表示当前节点node为空,即前一个节点没有左子树了
print node.elem,
node = node.rchild #开始查看它的右子树
def later_stack(self, root):
"""利用堆栈实现树的后序遍历"""
if root == None:
return
myStack1 = []
myStack2 = []
node = root
myStack1.append(node)
while myStack1: #这个while循环的功能是找出后序遍历的逆序,存在myStack2里面
node = myStack1.pop()
if node.lchild:
myStack1.append(node.lchild)
if node.rchild:
myStack1.append(node.rchild)
myStack2.append(node)
while myStack2: #将myStack2中的元素出栈,即为后序遍历次序
print myStack2.pop().elem,
def level_queue(self, root):
"""利用队列实现树的层次遍历"""
if root == None:
return
myQueue = []
node = root
myQueue.append(node)
while myQueue:
node = myQueue.pop(0)
print node.elem,
if node.lchild != None:
myQueue.append(node.lchild)
if node.rchild != None:
myQueue.append(node.rchild)
if __name__ == '__main__':
"""主函数"""
elems = range(10) #生成十个数据作为树节点
tree = Tree() #新建一个树对象
for elem in elems:
tree.add(elem) #逐个添加树的节点
print '队列实现层次遍历:'
tree.level_queue(tree.root)
print '\n\n递归实现先序遍历:'
tree.front_digui(tree.root)
print '\n递归实现中序遍历:'
tree.middle_digui(tree.root)
print '\n递归实现后序遍历:'
tree.later_digui(tree.root)
print '\n\n堆栈实现先序遍历:'
tree.front_stack(tree.root)
print '\n堆栈实现中序遍历:'
tree.middle_stack(tree.root)
print '\n堆栈实现后序遍历:'
tree.later_stack(tree.root)
---------------------
例1.
递归法的
递归
# 时间复杂度:O(n),n为节点数,访问每个节点恰好一次。
# 空间复杂度:空间复杂度:O(h),h为树的高度。最坏情况下需要空间O(n),平均情况为O(logn)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if root == None:
return []
return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)
前序遍历
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if root ==None:
return []
return ([root.val]+self.preorderTraversal(root.left)+self.preorderTraversal(root.right))
后序遍历
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if root == None:
return []
return (self.postorderTraversal(root.left) + self.postorderTraversal(root.right)+[root.val] )
不会的知识
check()函数是当满足查找条件以及向最佳答案压缩的方向返回true,不满足条件返回false
return语句放置在循环体内,循环一共执行了三次,相当于前前后后一共有3个return语句,根据上文对return语句用法介绍——遇到的第一个return即返回(退出def块),所以,当第一个return上传完毕后,直接退出def
if not a:我觉得是判断a是否为空的写法:如果a为空
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
def recur(L, R):
if not L and not R: return True #就是指如果L为空并且R为空,返回True
if not L or not R or L.val != R.val: return False
return recur(L.left, R.right) and recur(L.right, R.left)
return not root or recur(root.left, root.right)