搜索:顺序,二分,二叉,哈希

博客主要介绍了二分查找和二叉树相关知识。二分查找只能用于有序顺序表,有非递归和递归方式,时间复杂度为O(logn)。二叉树每个节点最多含两个子树,介绍了其性质、存储方式、遍历方法(深度优先和广度优先),还提及了树的构造及相关复杂度分析。

二分

二分查找只能用有序顺序表:折半查找

一些小问题: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

二叉树的性质

  1. 在二叉树的i层至多有2^(i-1)
  2. 深度为k的二叉树最多有2^k-1节点

遍历

二叉树的实现

广度遍历

深度遍历

  1. 先序遍历        根左右
  2. 中序遍历        左根右
  3. 后序遍历        左右根

  • 树的构造
  • 递归实现先序遍历、中序遍历、后序遍历
  • 堆栈实现先序遍历、中序遍历、后序遍历
  • 队列实现层次遍历
#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)

深度优先搜索

广度优先搜索(BFS)。BFS 通常借助 队列 的先入先出特性来实现。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值