剑指offer在线编程(08-08)【4】

Date: 2019-08-08

1.  二叉树中和为某一值的路径 (考察知识点:树)

解释: 

题目描述

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

# -*- 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):
        def subFindPath(root):
            if root:  # 如非空,则先放入缓存list:b
                b.append(root.val)
                # 若已到达叶子节点并且满足该路径的和等于预期的数字,则将b保存的缓存路径放入结果list:a
                if not root.right and not root.left and sum(b) == expectNumber:
                    a.append(b[:])
                else:
                    # 否则节点往左右孩子进行递归调用
                    subFindPath(root.left),subFindPath(root.right)
                b.pop()# 如已到达叶子节点,无论满足与否,不断往上删除最后一个元素,递归其他孩子节点。
        a, b = [], []
        subFindPath(root)
        return a

2.复杂链表的复制(考察知识点:链表)  (未完全解决!!!)

题目描述

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

注:此题比较难以思考,后续请多看!! 方法主要采取三步走的策略:复制原始链表的next指针,赋值原始链表的random指针,然后分离原始链表和复制的链表。

思路:

    1. 把复制的结点链接在原始链表的每一对应结点后面

       

    2. 把复制的结点的random指针指向被复制结点的random指针的下一个结点

    3. 拆分成两个链表,奇数位置为原链表,偶数位置为复制链表,注意复制链表的最后一个结点的next指针不能跟原链表指向同一个空结点None,next指针要重新赋值None(判定程序会认定你没有完成复制)

    

# -*- 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):
        if not pHead:
            return None
        dummy = pHead
        
        # first step, N' to N next
        while dummy:
            dummynext = dummy.next 
            copynode = RandomListNode(dummy.label)
            copynode.next = dummynext
            dummy.next = copynode 
            dummy = dummynext
        dummy = pHead
        
        # second step, random' to random'
        while dummy:
            dummyrandom = dummy.random
            copynode = dummy.next
            if dummyrandom:
                copynode.random = dummyrandom.next
            dummy = copynode.next
            
        # third step, split linked list 
        dummy = pHead
        copyHead = pHead.next
        while dummy:
            copyNode = dummy.next 
            dummynext = copyNode.next
            dummy.next = dummynext
            if dummynext:
                copyNode.next = dummynext.next
            else:
                copyNode.next = None
            dummy = dummynext
        return copyHead

另外一种思想:

# -*- 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
         
        head = pHead
        p_head = None
        new_head = None
         
        random_dic = {}
        old_new_dic = {}
         
        while head:
            node = RandomListNode(head.label)
            node.random = head.random
            old_new_dic[id(head)] = id(node)
            random_dic[id(node)] = node
            head = head.next
             
            if new_head:
                new_head.next = node
                new_head = new_head.next
            else:
                new_head = node
                p_head = node
                 
        new_head = p_head
        while new_head:
            if new_head.random != None:
                new_head.random = random_dic[old_new_dic[id(new_head.random)]]
            new_head = new_head.next
        return p_head

3.  二叉搜索树与双向链表 (考察知识:链表与树)

题目描述

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

本题需要将二叉搜索树转换为一个有序的双向链表:实际上就是一个中序遍历(左中右)的结果,只是需要将中序遍历的结果写成一个双向链表。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def __init__(self):
        self.listHead = None
        self.listTail = None
    def Convert(self, pRootOfTree):
        if pRootOfTree==None:
            return
        self.Convert(pRootOfTree.left)  # 左子树遍历
        # 以下部分是中间根节点的操作,包括初始节点
        if self.listHead==None:
            self.listHead = pRootOfTree
            self.listTail = pRootOfTree
        else:
            self.listTail.right = pRootOfTree
            pRootOfTree.left = self.listTail
            self.listTail = pRootOfTree 
        self.Convert(pRootOfTree.right) # 右子树遍历
        return self.listHead

参考一篇博文的详细解释:https://blog.csdn.net/u010005281/article/details/79657259,附上原文(建议回看这篇博客,python版本解释的非常到位!)。

4.  字符串的排列 (考察知识点:字符串+递归+动态规划)

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述:

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

分析:实际上就是一个全排列,然后基于所有的全排列的结果去重+排序输出即可,

如果可以调用itertools库,可以如下超级简单操作:

# -*- coding:utf-8 -*-
import itertools
class Solution:
    def Permutation(self, ss):
        # write code here
        if not ss:
            return []
        list_o = list(itertools.permutations(ss, len(ss)))
        return sorted(list(set(list_o)))
# ss ='AabBc'
print(Permutation(ss))
[('A', 'B', 'a', 'b', 'c'), ('A', 'B', 'a', 'c', 'b'), ('A', 'B', 'b', 'a', 'c'), ('A', 'B', 'b', 'c', 'a'), ('A', 'B', 'c', 'a', 'b'), ('A', 'B', 'c', 'b', 'a'), ('A', 'a', 'B', 'b', 'c'), ('A', 'a', 'B', 'c', 'b'), ('A', 'a', 'b', 'B', 'c'), ('A', 'a', 'b', 'c', 'B'), ('A', 'a', 'c', 'B', 'b'), ('A', 'a', 'c', 'b', 'B'), ('A', 'b', 'B', 'a', 'c'), ('A', 'b', 'B', 'c', 'a'), ('A', 'b', 'a', 'B', 'c'), ('A', 'b', 'a', 'c', 'B'), ('A', 'b', 'c', 'B', 'a'), ('A', 'b', 'c', 'a', 'B'), ('A', 'c', 'B', 'a', 'b'), ('A', 'c', 'B', 'b', 'a'), ('A', 'c', 'a', 'B', 'b'), ('A', 'c', 'a', 'b', 'B'), ('A', 'c', 'b', 'B', 'a'), ('A', 'c', 'b', 'a', 'B'), ('B', 'A', 'a', 'b', 'c'), ('B', 'A', 'a', 'c', 'b'), ('B', 'A', 'b', 'a', 'c'), ('B', 'A', 'b', 'c', 'a'), ('B', 'A', 'c', 'a', 'b'), ('B', 'A', 'c', 'b', 'a'), ('B', 'a', 'A', 'b', 'c'), ('B', 'a', 'A', 'c', 'b'), ('B', 'a', 'b', 'A', 'c'), ('B', 'a', 'b', 'c', 'A'), ('B', 'a', 'c', 'A', 'b'), ('B', 'a', 'c', 'b', 'A'), ('B', 'b', 'A', 'a', 'c'), ('B', 'b', 'A', 'c', 'a'), ('B', 'b', 'a', 'A', 'c'), ('B', 'b', 'a', 'c', 'A'), ('B', 'b', 'c', 'A', 'a'), ('B', 'b', 'c', 'a', 'A'), ('B', 'c', 'A', 'a', 'b'), ('B', 'c', 'A', 'b', 'a'), ('B', 'c', 'a', 'A', 'b'), ('B', 'c', 'a', 'b', 'A'), ('B', 'c', 'b', 'A', 'a'), ('B', 'c', 'b', 'a', 'A'), ('a', 'A', 'B', 'b', 'c'), ('a', 'A', 'B', 'c', 'b'), ('a', 'A', 'b', 'B', 'c'), ('a', 'A', 'b', 'c', 'B'), ('a', 'A', 'c', 'B', 'b'), ('a', 'A', 'c', 'b', 'B'), ('a', 'B', 'A', 'b', 'c'), ('a', 'B', 'A', 'c', 'b'), ('a', 'B', 'b', 'A', 'c'), ('a', 'B', 'b', 'c', 'A'), ('a', 'B', 'c', 'A', 'b'), ('a', 'B', 'c', 'b', 'A'), ('a', 'b', 'A', 'B', 'c'), ('a', 'b', 'A', 'c', 'B'), ('a', 'b', 'B', 'A', 'c'), ('a', 'b', 'B', 'c', 'A'), ('a', 'b', 'c', 'A', 'B'), ('a', 'b', 'c', 'B', 'A'), ('a', 'c', 'A', 'B', 'b'), ('a', 'c', 'A', 'b', 'B'), ('a', 'c', 'B', 'A', 'b'), ('a', 'c', 'B', 'b', 'A'), ('a', 'c', 'b', 'A', 'B'), ('a', 'c', 'b', 'B', 'A'), ('b', 'A', 'B', 'a', 'c'), ('b', 'A', 'B', 'c', 'a'), ('b', 'A', 'a', 'B', 'c'), ('b', 'A', 'a', 'c', 'B'), ('b', 'A', 'c', 'B', 'a'), ('b', 'A', 'c', 'a', 'B'), ('b', 'B', 'A', 'a', 'c'), ('b', 'B', 'A', 'c', 'a'), ('b', 'B', 'a', 'A', 'c'), ('b', 'B', 'a', 'c', 'A'), ('b', 'B', 'c', 'A', 'a'), ('b', 'B', 'c', 'a', 'A'), ('b', 'a', 'A', 'B', 'c'), ('b', 'a', 'A', 'c', 'B'), ('b', 'a', 'B', 'A', 'c'), ('b', 'a', 'B', 'c', 'A'), ('b', 'a', 'c', 'A', 'B'), ('b', 'a', 'c', 'B', 'A'), ('b', 'c', 'A', 'B', 'a'), ('b', 'c', 'A', 'a', 'B'), ('b', 'c', 'B', 'A', 'a'), ('b', 'c', 'B', 'a', 'A'), ('b', 'c', 'a', 'A', 'B'), ('b', 'c', 'a', 'B', 'A'), ('c', 'A', 'B', 'a', 'b'), ('c', 'A', 'B', 'b', 'a'), ('c', 'A', 'a', 'B', 'b'), ('c', 'A', 'a', 'b', 'B'), ('c', 'A', 'b', 'B', 'a'), ('c', 'A', 'b', 'a', 'B'), ('c', 'B', 'A', 'a', 'b'), ('c', 'B', 'A', 'b', 'a'), ('c', 'B', 'a', 'A', 'b'), ('c', 'B', 'a', 'b', 'A'), ('c', 'B', 'b', 'A', 'a'), ('c', 'B', 'b', 'a', 'A'), ('c', 'a', 'A', 'B', 'b'), ('c', 'a', 'A', 'b', 'B'), ('c', 'a', 'B', 'A', 'b'), ('c', 'a', 'B', 'b', 'A'), ('c', 'a', 'b', 'A', 'B'), ('c', 'a', 'b', 'B', 'A'), ('c', 'b', 'A', 'B', 'a'), ('c', 'b', 'A', 'a', 'B'), ('c', 'b', 'B', 'A', 'a'), ('c', 'b', 'B', 'a', 'A'), ('c', 'b', 'a', 'A', 'B'), ('c', 'b', 'a', 'B', 'A')]

# 更简单的版本:(通过)
# -*- 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)))))

但是有时候面试时并不能调用该库,所以实际上考察的是全排列的写法:(递归思想)

# -*- coding:utf-8 -*-
class Solution:
    def Permutation(self, ss):
        if len(ss) <=0:
            return []
        res = list()
        self.perm(ss,res,'')
        uniq = list(set(res)) 
        return sorted(uniq)
    def perm(self,ss,res,path):
        if ss=='':
            res.append(path)
        else:
            for i in range(len(ss)):
                self.perm(ss[:i]+ss[i+1:],res,path+ss[i])

5.  数组中出现次数超过一半的数字

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路:本题可以借用collections中的Counter库,其返回的是对于该字符串中每一个字符的频次统计的字典。然后计算出字符串长度的一半,然后比较字典中每一个字符的频次与长度半径,大于则输出;不存在大于则返回0.

# -*- coding:utf-8 -*-
import collections
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        if len(numbers)==0:
            return 0
        c = collections.Counter(numbers)
        half = len(numbers)/2
        for k, v in c.items():
            if v > half:
                return k
        return 0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  


  

 

 

 

    
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值