剑指offer刷题

 本文题目为剑指offer上的题目:四道,用python写的,牛客网上运行。

  1. 复杂链表的复制

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

  3.  二叉搜索树的后序遍历序列

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

  1. 题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的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):
        # 按照思路2来写的
        if not pHead:
            return None
        nHead = RandomListNode(pHead.label)
        pCurrent = pHead.next
        nCurrent = nHead
        # 初始化映射
        mapper = {}
        # 需要注意,要特别添加一个None到None的映射!!
        mapper[id(pHead)] = nHead
        mapper[id(None)] = None
        # 原样复制链表
        while(pCurrent):
            node = RandomListNode(pCurrent.label)
            nCurrent.next = node
            nCurrent = node
            mapper[id(pCurrent)] = node
            pCurrent = pCurrent.next
        # 添加random指针
        pCurrent = pHead
        nCurrent = nHead
        while(pCurrent):
            nCurrent.random = mapper[id(pCurrent.random)]
            pCurrent = pCurrent.next
            nCurrent = nCurrent.next
        return nHead

 

 

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

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

首先要理解题意。后面注明了路径的定义为到叶节点,即题目的意思为,要求的是从根节点开始到叶子节点的和为输入整数。注意为叶子节点处停止,根节点处开始。

 

class Solution:
    def FindPath(self, root, expectNumber):
        def subFindPath(root):
            if root:
                b.append(root.val)
                if not root.right and not root.left and sum(b) == expectNumber:
                    a.append(b[:])#深拷贝,只有这样a中添加的才是正确的结果,否则递归返回时改变了b内的内容会让a中已经保存的内容也变掉
                else:
                    subFindPath(root.left),subFindPath(root.right)
                b.pop()
        a, b = [], []
        subFindPath(root)
        return a

 

 

3.二叉搜索树的后序遍历序列

题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

# -*- coding:utf-8 -*-
        # write code here
        #二叉搜索树的后续遍历有啥特点?
        #二叉搜索树,也称有序二叉树,排序二叉树,是指一棵空树或者具有下列性质的二叉树:
#1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
#2. 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
#3. 任意节点的左、右子树也分别为二叉查找树。
#4. 没有键值相等的节点。
#https://blog.csdn.net/yixianfeng41/article/details/52802855
#二叉搜索树讲解很好的视频,https://www.bilibili.com/video/av45322333


class Solution:
    def VerifySquenceOfBST(self, sequence):
        # 递归的过程,每一个子树最后一个元素是根节点,且前一段都比它小,后一段都比它大
        if not sequence:
            return False
        # 找到根节点
        root = sequence[-1]
        split = len(sequence) - 1
        # 找到划分点
        for i in range(0, len(sequence)-1):
            if sequence[i] >= root:
                split = i
                break
        # 确认后半段都比root大
        for i in range(split, len(sequence)-1):
            if sequence[i] <= root:
                return False
        # 递归检查前半段和后半段
        left = True
        if split > 0:
            # 前半段至少有两个元素,才递归
            left = self.VerifySquenceOfBST(sequence[0:split])
        right = True
        if split < len(sequence) - 1:
            # 后半段至少有两个元素,才递归
            right = self.VerifySquenceOfBST(sequence[split:-1])
        return left and right

 

 

 

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

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


可以采用一种计数的方法。规则是,记下一个数字target和一个count。
#遍历数组,当遍历到下一个元素next时,如果和当前记下的数字target相同,
#那么count+1,如果不同,count-1(相当于两个抵消了)。如果在遍历到下一个元素next之前,
#count已经被减为0了,则说明之前的抵消干净了,此时应当将target设置为next,
#count记为1。仔细想一下,这种方法就是模拟了不同的元素两两抵消。
#所以最后一个使count设为1的元素,战胜了其他所有元素,它就是出现次数多于一半的目标。
#需要注意:上面的前提是目标一定存在。如果目标不存在,比如[1,2,3,3,4],
#使count最后一次被设置为1时的元素是3,但3出现的次数小于一半。所以最终还要再遍历一遍,
#判断一下找到的元素是否个数真的多于一半。

 


class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        if not numbers:
            return 0
        target = numbers[0]
        count = 1
        for i in range(1, len(numbers)):
            if count == 0:
                target = numbers[i]
                count = 1
            elif target == numbers[i]:
                count += 1
            elif target != numbers[i]:
                count -= 1
        # count==0说明刚好消干净了,没有个数多于一半的,就不用再数了直接返回0
        if count == 0:
            return 0
        count = 0
        for i in range(0, len(numbers)):
            if numbers[i] == target:
                count += 1
        if count > len(numbers)/2:
            return target
        else:
            return 0

感谢与参考:

https://codingcat.cn/article/26#%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值