《剑指offer》python实现

五一回来,继续做《剑指offer》,写代码使我快乐T_T

python的很多语法还需要继续熟练,加以理解与掌握



树的子结构

题目描述:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

class Solution:
    def HasSubtree(self, p1, p2):
        if p1==None or p2==None:
            return False
        else:
            return self.judge(p1,p2)
    #由于递归中如果递归到p2为空树,应该返回True,因此需要重新建立一个递归函数
    def judge(self,p1,p2):
        if p2==None:#当p2为空,返回true
            return True
        if p1==None:#当p1为空的时候,p2必须一样为空
            return p1==p2
        result=False
        if p1.val==p2.val:#当p1,p2值一样的时候,开始递归判断p1,p2的左右树
            result=self.judge(p1.left,p2.left) and self.judge(p1.right,p2.right)
        return result or self.judge(p1.left,p2) or self.judge(p1.right,p2)
        #返回result的判断结果,或者在p1的左右树中查找

本质上使用的是递归调用判断函数,但是由于题目要求,空树不是任意一个树的子结构,因此需要将递归调用的函数重新写【递归的最后终止条件是空树认为是相同的】

二叉树的镜像

题目描述:
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树

	     8
	   /   \
	  6     10
	 / \    / \
	5  7    9 11
	镜像二叉树
	     8
	   /  \
	  10   6
	 / \  / \
	11 9  7  5
# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回镜像树的根节点
    def Mirror(self, root):
        # 由于题目要求将源二叉树变化为镜像,因此不能新建一个二叉树
        if root==None:
            return
        root.left,root.right=root.right,root.left#需要在源二叉树上进行操作,交换左右树
        self.Mirror(root.left)#递归左树
        self.Mirror(root.right)#递归右树
        return

在这个题中,递归的终止节点是该根节点为空则返回,递归的时候,先将左右子树根节点对换,然后递归调用镜像函数对左树进行处理,然后递归调用镜像函数对右树进行处理即可。

注意python中可以直接使用语句:

a,b=b,a

来对a,b元素进行对换,效果等同于:

temp=a
a=b
b=temp

顺时针打印矩阵

题目描述:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
例如,如果输入如下4X4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        n=len(matrix)
        m=len(matrix[0])
        ls=[]
        up,down,left,right=0,n,0,m#定义好四个边界
        while(True):
            #分为四个步骤,右下左上,打印的过程中,如果遇到边界重合,表示打印完毕,退出循环
            #向右打印,打印完一行,上边界向下移动一个位置
            i=up
            for j in range(left,right,1):
                ls.append(matrix[i][j])
            up+=1
            if(up==down):
                break
            #向下打印,打印完一列,右边界向左移动一个位置
            j=right-1
            for i in range(up,down,1):
                ls.append(matrix[i][j])
            right-=1
            if(right==left):
                break
            #向左打印,打印完一行,下边界向上移动一个位置
            i=down-1
            for j in range(right-1,left-1,-1):
                ls.append(matrix[i][j])
            down-=1
            if(up==down):
                break
            #向上打印,打印完一列,左边界向右移动一个位置
            j=left
            for i in range(down-1,up-1,-1):
                ls.append(matrix[i][j])
            left+=1
            if(right==left):
                break
        return ls

打印的过程分解为向右,向下,向左,向上,每次执行完一个步骤,将打印边界进行修改,如果边界下一个步骤的边界重合,表示循环完毕退出即可。

包含min函数的栈

题目描述:
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。

class Solution:
    def __init__(self):
        self.stack=[]
        self.minstack=[]#定义存储最小值的辅助堆栈
    def push(self, node):
        self.stack.append(node)
        if not self.minstack:#如果辅助栈没有元素直接将node元素push进去
            self.minstack.append(node)
        else:#如果有元素,需要比较node元素与辅助栈的顶元素的大小进行push
            if node<self.minstack[-1]:#如果追加的元素小于栈顶的元素,辅助堆栈的栈顶push该元素
                self.minstack.append(node)
            else:#如果追加的元素大于栈顶的元素,辅助堆栈的栈顶push堆栈栈顶的元素
                self.minstack.append(self.minstack[-1])
    def pop(self):
        if self.stack:#辅助堆栈与元素堆栈同时pop
            self.minstack.pop()
            return self.stack.pop()
        else:
            return None
    def top(self):
        return self.stack[-1]
    def min(self):
        return self.minstack[-1]

本题要求最小元素的查找函数的时间复杂度为O(1),因此不能要将每一次压栈操作后的最小元素储存起来,因此比较好想到的是,使用另一个辅助栈,每次压栈的时候存储当前数组栈的最小元素即可。需要注意pop的时候要同时将数组栈的顶端元素与辅助栈的顶端元素同时pop,调用min函数的使用只要将辅助栈的顶端元素显示出来即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值