《剑指offer》python实现

继续《剑指offer》的做题之旅,发现闭门造车的学习方法实在是太过慢,还是不断阅读网上各路大神的各种方法,站在巨人的肩膀上的学习效率高【其实是自己的方法太差】


本文题目:

    • 二叉树中和为某一值的路径
    • 复杂链表的复制
    • 二叉搜索树与双向链表


二叉树中和为某一值的路径

题目描述:
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

# -*- coding:utf-8 -*-
class TreeNode:
     def __init__(self, x):
         self.val = x
         self.left = None
         self.right = None

class Solution:
    def __init__(self):
    	#记录结果的二维数组与记录路径的一维数组
        self.result=[]
        self.path=[]

    # 返回二维列表,内部每个列表表示找到的路径
    def FindPath(self, root, expectNumber):
        # write code here
        if not root or root.val>expectNumber:
            return self.result
        self.findsinglepath(root,expectNumber)
        return self.result


    def findsinglepath(self,root,sum):
        if not root:
            return self.result
        #记录当前节点
        self.path.append(root.val)
        #将sum减去目前添加的root的值
        sum-=root.val
        #如果该节点的左右子树都为空,判断路径的加和是不是等于结果
        if not root.left and not root.right:
            if sum==0:
                self.result.append(self.path[:])
        #递归调用左右子树的查询结果
        if root.left:
            self.findsinglepath(root.left,sum)
        if root.right:
            self.findsinglepath(root.right,sum)
        #左右子树都查找完pop根节点
        self.path.pop()
        return self.result

此题其实为二叉树的前序遍历,前序遍历如果和为要求,且该路径终点为叶子节点,将该路径储存在二维数组中。其中前序遍历使用递归实现。

复杂链表的复制

题目描述:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

# -*- coding:utf-8 -*-
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        newnode=self.cloneonenode(pHead)
        return newnode

    def cloneonenode(self,old):
        #如果该节点为空,返回一个复制的空节点
        if not old:
            return None
        #复制值
        newnode=RandomListNode(old.label)
        #复制下一个节点
        newnode.next=self.cloneonenode(old.next)
        #记录随机指向节点
        newnode.random=old.random
        return newnode

本题思路使用递归实现,递归时,先根据久节点建立新节点,然后递归复制节点的下一节点,之后将新节点的随机指针指向原节点的随机指针【这里其实是将新链表的所有随机指针指向旧链表的随机指针的指向,因此并不能算是完全的复制】

网上大神们的正确方法实际是三步骤:
1.将新节点复制到原节点的后边,这样奇数位为原链表,偶数为为新链表
2.将原链表中存在随机指针的节点的后一节点【该原节点的复制节点】的随机指针指向原节点的随机指针节点的下一节点
3.分离原链表与新链表

class RandomListNode:
     def __init__(self, x):
         self.label = x
         self.next = None
         self.random = None

class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        if not pHead:
            return None
        ptr=pHead
        while ptr:
            #临时储存ptr的下一节点
            tep=ptr.next
            #将ptr的下一节点设为复制的节点
            ptr.next=self.cloneonenode(ptr)
            #复制节点的下一节点设为tep
            ptr.next.next=tep
            #ptr移动到tep上
            ptr=tep
        #以上完成了新旧链表的交替,接下来将所有节点中存在随机指针的新节点调整
        ptr=pHead
        while ptr:
            #如果ptr存在random指针
            if ptr.random:
                ptr.next.random=ptr.random.next
            ptr=ptr.next.next
        #以上将随机指针设置完毕,之后将新旧链表分离
        p1=pHead
        p2=pHead.next
        new=pHead.next#需要将新节点的头指针记录下来
        while True:
            p1.next=p2.next
            p1=p1.next
            if not p1:#一但原链表到头,退出循环
                break
            p2.next=p1.next
            p2=p2.next
        return new

    def cloneonenode(self,old):
        #如果该节点为空,返回一个复制的空节点
        if not old:
            return None
        newnode=RandomListNode(old.label)
        return newnode

二叉搜索树与双向链表

题目描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    #定义mid数组来储存中序遍历结果,对于二叉搜索树,中序遍历结果就是有序的序列
    def __init__(self):
        self.mid=[]

    #转换函数将按照中序的序列结果,将后一节点的左树设为前一节点,前一节点的右树设为后一节点
    def Convert(self, pRootOfTree):
        # write code here
        if not pRootOfTree:
            return None
        self.inorder(pRootOfTree)
        for i in range(len(self.mid)-1):
            self.mid[i].right=self.mid[i+1]
            self.mid[i+1].left=self.mid[i]
        return self.mid[0]

    #将中序遍历的结果放在mid数组中
    def inorder(self,root):
        if not root:
            return
        self.inorder(root.left)
        self.mid.append(root)
        self.inorder(root.right)
        return

由于二叉搜索树的中序遍历结果为一个有序的序列,因此将原树变为双向有序链表只要将中序序列顺序储存到一个数组,然后对数组中每一个元素,右树设为下一节点,左树设为前一节点即可

你可能感兴趣的:(《剑指offer》python实现)