剑指 offer 编程 66 题 Python 代码 
1  题目描述:在一个二维数组中(每个一维数组的长度相同),每一行都按照从到右递增的
顺序排列,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维
数组和一个整数,判断数组中是否含有该整数。 
解析:由于每行从左到右递增,每列从上到下递增,因此每列的最后一个元素最大;函数可
以从每行的最后一个元素 A 开始判断,如果目标 B 大于 A,则从下一行最后一个元素开始判
断,如果 B 小于 A,则往前移一列,从新列开始判断 
代码如下: 
class Solution: 
        # array  二维列表 
        def Find(self, target, array): 
                # write code here 
                row = len(array) 
                col = len(array[0]) 
                j=0 
                i= col‐1 
                while j < row and i > ‐1: 
                        if array[j][i] > target: 
                                i‐=1 
                        elif array[j][i] < targrt: 
                                j+=1 
                        else: 
                                return 'ture' 
                        return 'false' 
2  题目描述:请实现一个函数,将一个字符串中的每个空格替换成”%20”。例如,当字符串
为 We Are Happy  则经过替换之后的字符串为 We%20Are%20Happy。 
解析:Python 中提供字符串替换函数 replace()函数,replace()方法的语法:str.replace(old, new[, 
max]),old 将被替换的子字符串,  new 新字符串,用于替换 old 子字符串,max 可选字符
串,替换不超过 max 次 
代码如下: 
class Solution: 
        # s  源字符串 
        def replaceSpace(self, s): 
                return s.replace(' ', '%20') 
                # write code here         
3 题目描述:输入一个链表,按链表值从尾到头的顺序返回一个 ArrayList。 
解析:将链表的每个值取出来然后存放到一个列表 ArrayList 中,对于 ArrayList 列表可以将
其反置(Python 中提供 reverse()方法,用法是 List.reverse(),但该方法不返回值);此外 Python
中还提供列表的插入函数 insert()函数,用法是 list.insert(index,  obj),  index—对象 obj 需要
插入的索引位置,同样该方法没有返回值,但会在列表指定位置插入对象。 
代码如下:(采用 insert()方法) 
# class ListNode: 
#          def __init__(self, x): 
#                  self.val = x 
#                  self.next = None 
 
class Solution: 
        #  返回从尾部到头部的列表值序列,例如[1,2,3] 
        def printListFromTailToHead(self, listNode): 
                midArrayList = [] 
                while listNode: 
                        midArrayList.insert(0, listNode.val) 
                        listNode = listNode.next 
                return midArrayList 
                # write code here 
4  题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的
前序遍历和中序遍历的结果中都不包含重复的数字。例如输入前序遍历序列{1, 2, 4, 7, 3, 5, 
6,8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建二叉树并返回。 
解析:对于前序序列,第一个元素(如果存在)为根节点(1),由于元素各不相同,则根据中序
序列,可以判断出根节点的左子树的中序序列(4, 7,2)和右子树的中序序列(5, 3, 8, 6),同时可
以判断出根节点的左子树的前序序列(2, 4, 7)  和右子树的前序序列(3, 5, 6, 8)。因此可以根据
递归重建该二叉树 
代码如下: 
# ‐*‐ coding:utf‐8 ‐*‐ 
# class TreeNode: 
#          def __init__(self, x): 
#                  self.val = x 
#                  self.left = None 
#                  self.right = None 
class Solution: 
        #  返回构造的 TreeNode 根节点 
def reConstructBinaryTree(self, pre, tin): 
        if len(pre) == 0: 
                return None 
        elif len(pre) == 1: 
                return TreeNode(pre[0]) 
        else: 
                treeNode = TreeNode(pre[0]) 
treeNode.left = self. reConstructBinaryTree(pre[1:tin.index(pre[0])+1], 
tin[:tin.index(pre[0])]) 
treeNode.right = self. reConstructBinaryTree(pre[tin.index(pre[0])+1:], 
tin[tin.index(pre[0])+1:]) 
return treeNode 
                #write code here 
5  题目描述:用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。队列中的元素为 int
类型。 
解析:栈 A 用来做入队列,  栈 B 用来做出队列,当栈 B 为空时,栈 A 全部出栈到栈 B,栈
B 再出栈(即出队列) 
代码如下: 
class Solution: 
def __init__(self): 
        self.stackA = [] 
        self.stackB = [] 
def push(self, node): 
        self.stackA.append(node) 
def pop(self): 
        if self.stackB: 
                return self.stackB.pop() 
        else: 
                while self.stackA: 
                        self.stackB.append(self.stackA.pop()) 
                return self.stackB.pop() 
6.题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输
入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 
3, 4, 5}的一个旋转,该数组的最小值为 1。NOTE:  给出的所有元素都大于 0,若数组大小为
0,请返回 0. 
解析:由于数组是两段不减的,因此,可以找出数组中第一个最小的值,将该值前面的所有
元素移到数组的末尾即可。 
代码如下: 
class Solution: 
        def minNumberInRotateArray(self, rotateArray): 
                if len(rotateArray) == 0: 
                        return 0 
                else: 
                        min_value = min(rotateArray) 
                        min_index = rotateArray.index(min_value) 
                        newArray = rotateArray[min_index:] + rotateArray[:min_index] 
                        return newArray[0] 
                # write code here 
7.题目描述:大家都知道斐波那契数列,现在要求输入一个整数 n,请你输出斐波那契数列
的第 n 项(从 0 开始,第 0 项为 0). 
n<=39 
解析:斐波那契数列有一个很重要的性质,后面一项是前两项的和(n>=3),前两项都是 1,很
容易想到用递归求解第 n 项的值,但是递归需要消耗更多的内存,因此可以使用动态规划,
用两个变量分别保持上次的计算结果和上上次的计算结果 
代码如下: 
class Solution: 
        def Fibonacci(self, n): 
                a = 0 
                b = 1 
                if n <= 0: 
                        return 0 
                else: 
                        for i in range(n): 
                                a, b = b, a + b 
                        return a   
                # write code here 
8.  题目描述:一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级。求该青蛙跳上一个 n 级
的台阶总共有多少种跳法(先后次序不同算不同的结果) 
解析:由于青蛙一次只能跳一个台阶或者跳两个台阶,因此,我们可以考虑青蛙最后通过跳
一步或者跳两步到最后的台阶,假设青蛙一步跳到最后的台阶,那么 f(n)和 f(n‐1)的跳法是
一样多的;假如青蛙两步跳到最后的台阶,那么 f(n)和 f(n‐2)的跳法是一样的,故可以知道:
f(n)=f(n‐1)+f(n‐2)的递推公式。 
代码如下: 
class Solution: 
        def jumpFloor(self, number): 
                a = 0 
                b = 1 
                if number == 0: 
                        return 0 
                else: 
                        for i in range(number): 
                                a, b = b, a + b 
                        return b 
                # write code here 
9  题目描述:一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级......它也可以跳上 n 级。求
该青蛙跳上一个 n 级的台阶总共有多少种跳法。 
解析:考虑这样的一种情况,青蛙最后一跳跳到最后台阶,这样的每一跳都是一种独立的方
法,因此,青蛙可以从 n‐1 台阶跳一次,也可以从 n‐2 台阶跳两次,依次类推,则每次跳的
方案有 f(n‐1), f(n‐2), ... f(1)种,此时 f(n) = f(n‐1)+ f(n‐2) + f(n‐3) + ... + f(1),  可以推出 f(n) = 
2f(n‐1). 
代码如下: 
class Solution: 
        def jumpFloorII(self, number): 
                count = 1 
                for i in range(number ‐ 1): 
                        count = count * 2 
                return count   
                # write code here 
10  题目描述:我们可以用 2 * 1  的小矩形横着或者竖着去覆盖更大的矩形。请问用 n 个 2 * 
1  的小矩形无重叠地覆盖一个 2 * n 的大矩形,总共用多少种方法? 
分析:对于矩形的覆盖,可以考虑最后的覆盖是横着还是竖着的小矩形,如果是竖着(占一
列),则有 f(n‐1)种覆盖方法,如果是横着(占两行),则有 f(n‐2)  种覆盖方法,因此一共有 f(n) 
= f(n‐1) + f(n‐2)种覆盖方法。 
代码如下: 
class Solution: 
        def rectCover(self, number): 
                if number == 0: 
                        return 0 
                a = 1 
                b = 1 
                for i in range(number): 
                        a, b = b, a + b 
                return a   
                # write code here 
11  题目描述:输入一个整数,输出该数二进制表示中 1 的个数。其中负数用补码表示。 
解析:在 Python 中 int 型整数是用 32 位二进制代码存储的,负数按照补码的形式存储的,
因此可以将该整数的 32 位二进制代码,一位一位的与 1 做‘&’运算,运算结果的和便是 1
的个数 
代码如下: 
class Solution: 
        def NumberOf1(self, n): 
                count = 0 
                for i in range(32): 
                        count = count + ((n >> i) & 1) #    ‘+’的运算级比’&’  高,切记加上’()’ 
                return count 
12  题目描述:给定一个 double 类型的浮点数 base 和 int 类型的整数 exponent。求 base 的
exponent 次方。 
解析:Python 中有计算次方的运算符  ’**’,因此直接使用即可。如果不使用’**’运算符,那
么需要判断 exponent 正负以及是否为 0,  对于 exponent 的正负,只需要是正的情况,记其
结果为 result,负的情况直接 1.0/result 即可计算;此外还需要判断 base 是否为 0 
代码如下: 
class Solution: 
        def Power(self, base, exponent): 
                result = 1 
                if base == 0: 
                        return 0 
                if exponent == 0: 
                        return 1 
                else: 
                        for i in range(abs(exponent)): 
                                result = base * result 
                        if exponent > 0: 
                                return result 
                        else: 
                                return 1.0/result 
                # write code here 
13  题目描述:输入一个整数数组,实现一个函数来调用该数组中数字的顺序,使得所有的
奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶
数之间的相对位置不变。 
解析:可以遍历整个数组,将奇数和偶数分别放在不同的列表中,最后,再合并两个列表。 
代码如下: 
class Solution: 
        def reOrderArray(self, array): 
                odd_numbers = [] 
                even_numbers = [] 
                for i in array: 
                        if i % 2 == 1: 
                                odd_numbers.append(i) 
                        else: 
                                even_numbers.append(i) 
                return odd_numbers + even_numbers 
                # write code here 
14  题目描述:输入一个链表,  输出该链表中倒数第 k 个结点。 
解析:由于是链表,则可以将链表中的每一个元素保存到列表中,在列表中寻找倒数第 k
个元素。 
代码如下: 
class Solution: 
def FindKthToTail(self, head, k): 
        t = [] 
        while head: 
                t.append(head) 
                head = head.next 
        if k > len(t) or k < 1: 
                return None 
        return t[‐k] 
15  题目描述:输入一个链表,反转链表后,输出新链表的表头。 
解析:可以将链表的每一个结点取出来,插入到新的链表表头,同时要保存原链表的下一个
结点。 
代码如下: 
# class ListNode: 
#          def __init__(self, x): 
#                  self.val = x 
#                  self.next = None 
class Solution: 
        #  返回 ListNode 
        last = None 
        def ReverseList(self, pHead): 
                if pHead == None: 
                        return pHead 
                last = None 
                while pHead: 
                        temp = pHead.next 
                        pHead.next = last 
                        last = pHead 
                        pHead = temp 
                return last 
16  题目描述:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成
后的链表满足单调不减规则。 
解析:从头开始比较两个链表元素的大小,将元素小的结点插入到新的链表中,直到一个链
表为空。这可以有两种方法,一种是递归实现,一种是非递归 
代码如下: 
递归: 
# class ListNode: 
#          def __init__(self, x): 
#                  self.val = x 
#                  self.next = None 
class Solution: 
        #  返回合并后列表 
        def Merge(self, pHead1, pHead2): 
                if pHead1 == None: 
                        return pHead2 
                if pHead2 == None: 
                        return pHead1 
                pMergedHead = None 
                if pHead1.val < pHead2.val: 
                        pMergedHead = pHead1 
                        pMergedHead.next = self.Merge(pHead1.next, pHead2) 
                else: 
                        pMergedHead = pHead2 
                        pMergedHead.next = self.Merge(pHead1, pHead2.next) 
                return pMergedHead 
                # write code here 
非递归: 
# class ListNode: 
#          def __init__(self, x): 
#                  self.val = x 
#                  self.next = None 
   
class Solution: 
        #  返回合并后列表 
        def Merge(self, pHead1, pHead2): 
                # write code here 
                mergeHead = ListNode(90) 
                p = mergeHead 
                while pHead1 and pHead2: 
                        if pHead1.val >= pHead2.val: 
                                mergeHead.next = pHead2 
                                pHead2 = pHead2.next 
                        else: 
                                mergeHead.next = pHead1 
                                pHead1 = pHead1.next 
                        mergeHead = mergeHead.next 
                if pHead1: 
                        mergeHead.next = pHead1 
                elif pHead2: 
                        mergeHead.next = pHead2 
                return p.next 
17  题目描述:输入两颗二叉树 A,B,判断 B 是不是 A 的子结构(PS:我们约定空树不是任
意一个树的子结构) 
解析:从 A 的判断根节点(约定和 B 的根节点开始判断的 A 结点称为判断根节点)和 B 开始匹
配,如果根节点一样,则分别判断左子树和右子树,重复上述过程,如果 B 为空则匹配,如
果 A 为空,或者两者的值不相等,则匹配不成功。 
代码如下: 
# class TreeNode: 
#          def __init__(self, x): 
#                  self.val = x 
#                  self.left = None 
#                  self.right = None 
class Solution: 
        def HasSubtree(self, pRoot1, pRoot2): 
                if not pRoot1 or not pRoot2: 
                        return False 
                return self.is_subtree(pRoot1, pRoot2) or self.HasSubtree(pRoot1.left, pRoot2) or 
self.HasSubtree(pRoot1.right, pRoot2) 
             
        def is_subtree(self, A, B): 
                if not B: 
                        return True 
                elif not A or A.val != B.val: 
                        return False 
                else: 
                        return self.is_subtree(A.left,B.left) and self.is_subtree(A.right, B.right) 
                # write code here 
18  题目描述:操作给的定的二叉树,将其变换为源二叉树的镜像。