剑指offer66题(Python)——第五天

25、二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。
假设输入的数组的任意两个数字都互不相同。
思路:要注意二叉搜索树的特点。
            BST的后序序列的合法序列是,对于一个序列S,最后一个元素是x (也就是根),如果去掉最后一个元素的序列为T,那么T满足:T可以分成两段,前一段(左子树)小于x,后一段(右子树)大于x,且这两段(子树)都是合法的后序序列。完美的递归定义。
# -*- coding:utf-8 -*-
class Solution:
    def VerifySquenceOfBST(self, sequence):
        # write code here
        length = len(sequence)
        if length == 0:
            return False
        if length == 1:
            return True
        root = sequence[-1]
        left = 0
        while sequence[left] < root:
            left += 1
        for j in range(left, length-1):
            if sequence[j] < root:
                return False
        return self.VerifySquenceOfBST(sequence[:left]) or self.VerifySquenceOfBST(sequence[left:length-1])

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

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

思路:当用前序遍历的方式访问某一结点时,我们把该结点添加到路径上,并累加该结点的值.如果该结点为叶结点并且路径中结点值的和刚好等于输入的整数,则当前的路径符合要求,我们把它打印出来。如果当前结点不是叶结点,则继续访问它的子结点.当访问结束后,递归函数将自动回到它的父结点。因此我们在函数退出之前要在路径上删除当前结点并减去当前结点的值,以确保返回父结点时路径刚好从根结点到父结点的路径。我们不难看出保存路径的数据结构实际上就是一个栈,因为路径要与递归调用状态一致,而递归调用的本质就是一个压栈和出栈的过程。

 
  
# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回二维列表,内部每个列表表示找到的路径
    def FindPath(self, root, expectNumber):
        # write code here
        if root is None:
            return []
        if root and not root.left and not root.right and root.val == expectNumber:
            return [[root.val]]
        temp=[]
        left = self.FindPath(root.left,expectNumber-root.val)
        right = self.FindPath(root.right,expectNumber-root.val)
        for i in left+right:
            temp.append([root.val]+i)
        return temp

27、复杂链表的复制

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的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):
        # write code here
        #复制节点在原节点之后
        if not pHead:
            return pHead
        cloNode = pHead
        while cloNode:
            node = RandomListNode(cloNode.label)
            node.next = cloNode.next
            cloNode.next = node
            cloNode = node.next
        #复制random节点
        cloNode = pHead
        while cloNode:
            node = cloNode.next
            if cloNode.random:
                node.random = cloNode.random.next
            cloNode = node.next
        #将新旧链表分离
        cloNode = pHead
        pHead = pHead.next
        while cloNode.next:
            node = cloNode.next
            cloNode.next = node.next
            cloNode = node
        return pHead

28、二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路: 递归版
解题思路:
1 .将左子树构造成双链表,并返回链表头节点。
2 .定位至左子树双链表最后一个节点。
3 .如果左子树链表不为空的话,将当前root追加到左子树链表。
4 .将右子树构造成双链表,并返回链表头节点。
5 .如果右子树链表不为空的话,将该链表追加到root节点之后。
6 .根据左子树链表是否为空确定返回的节点。
# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Convert(self, pRootOfTree):
        # write code here
        if pRootOfTree == None:
            return None
        if not pRootOfTree.left and not pRootOfTree.right:
            return pRootOfTree
        # 处理左子树
        self.Convert(pRootOfTree.left)
        left=pRootOfTree.left
        # 连接根与左子树最大结点
        if left:
            while(left.right):
                left=left.right
            pRootOfTree.left,left.right=left,pRootOfTree
        #处理右子树
        self.Convert(pRootOfTree.right)
        right=pRootOfTree.right
        if right:
            while(right.left):
                right=right.left
            pRootOfTree.right,right.left=right,pRootOfTree
        while(pRootOfTree.left):
            pRootOfTree=pRootOfTree.left
        return pRootOfTree
        

29、字符串的排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列。
例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
# -*- coding:utf-8 -*-
import itertools
class Solution:
    def Permutation(self, ss):
        # write code here
        if not ss:
            return []
        return sorted(list(set(map(''.join, itertools.permutations(ss)))))
以上是一种取巧的方法,更一般的做法:

class Solution:
    def Permutation(self, ss):
        if not len(ss):
            return []
        if len(ss) == 1:
            return list(ss)
        charList = list(ss)
        charList.sort()
        pStr = []
        for i in range(len(charList)):
            if i > 0 and charList[i] == charList[i-1]:
                continue
            temp = self.Permutation(ss[:i]+ss[i+1:])
            for j in temp:
                pStr.append(charList[i]+j)
        return pStr

30、数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
【思 路】由于要寻找的数字的出现次数超过了数组长度的一半,所以如果将该数组排序,那么它的中位数必然是我们要寻找的数字,所以我们的任务就是对该数组进行排序,而性能最好的快速排序的时间复杂度为O(nlogn)。
讲真,为什么这个会是第一个想到的思路,不太理解作者的思路。嗯,最开始映入我脑中的做法就是使用字典,把每一个不同的数字作为key,在数组中出现的次数作为value.
import collections
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        tmp = collections.Counter(numbers)
        x = len(numbers)/2
        for k, v in tmp.items():
            if v > x:
                return k
        return 0




猜你喜欢

转载自blog.csdn.net/u012114090/article/details/80406421