剑指offer66道练习题汇总——python版(持续更新)

本文整理了剑指Offer中的66道题目,涵盖了数组、字符串、链表、树、栈队列、递归循环等多种数据结构与算法,通过Python实现,包括二维数组查找、替换空格、链表操作、二叉树问题等,帮助读者提升算法能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.二维数组的查找(数组)

2.替换空格(字符串)

3.从尾到头打印链表(链表)

4.重建二叉树(树)

5.二叉树镜像(树)

6.用两个栈实现队列(栈和队列)

7.斐波那契数列(递归和循环)

8.旋转数组的最小数字(查找和排序)

9.跳台阶(递归与循环)

10.变态跳台阶(递归和循环)

11.单、双链表反转

12.矩形覆盖(递归和循环)

13.链表中倒数第k个节点

14.链表中环的入口结点

15.合并两个排序列表

16.顺时针打印数组

17.输入两个链表,找出它们的第一个公共结点。

18.删除排序链表中重复的结点

19.复杂链表的复制。

20.二叉搜索树第k小的结点。

21.二叉搜索树转为排序后的双向链表。

22.按字典序打印出符串中字符的所有排列。

23.找出数组中出现次数超过一半的数字。

24.之字形打印二叉树

25.从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

26.打印和为S的连续正数序列

27.求无序数组最小的k个数

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

29.连续子数组最大和

30.整数中1出现的次数

 

 

1.二维数组的查找(数组)

# -*- coding:utf-8 -*-
class Solution:
    # array 二维列表
    '''
    由于二维列表存在规律:每一行从左到右数值增加,每一列从上到下数值增加。
    将target与列表左下角元素比较,若target大于该元素,用于比较的元素的右移;若target小于该元素的话,用于比较的元素上移。
    也可以从右上角元素开始比较,道理相似。
    '''
    def Find(self, target, array):
        if len(array)==0:
            return False
        col=len(array[0])
        row=len(array)
        j=0
        i=row-1
        while j<=col-1 and i>=0:
            if(target==array[i][j]):
                return True
                break #如果找到target,就应跳出循环
            elif(target<array[i][j]):
                i-=1
            else:
                j+=1
        return False
while True:
    try:
        S=Solution()
        #字符串转为list
        L=list(eval(raw_input()))
        array=L[1]
        target=L[0]
        print(S.Find(target,array))
    except:
        break

2.替换空格(字符串)

# -*- coding:utf-8 -*-
class Solution:
    '''
    1.从前到后扫描s,用space_num记录空格的个数
    2.计算新的列表长度并创建新列表(即new_s)
    3.从后到前扫描原字符串s,进行替换,并将结果保存在new_s中
    '''
    def replaceSpace(self, s):
        # write code here
        s_len=len(s)
        space_num=0
  
        for i in range(s_len):
            if s[i]==" ":
                space_num+=1
        new_len=s_len+space_num*2
        new_s=[None for i in range(new_len)]
        for i in range(s_len-1,-1,-1):
            if (s[i]!=" "):
                new_s[i+space_num*2]=s[i]
            else:
                new_s[i+space_num*2]='0'
                new_s[i+space_num*2-1]='2'
                new_s[i+space_num*2-2]='%'
                space_num-=1 
 
        return "".join(new_s)

3.从尾到头打印链表(链表)

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
'''数组翻转'''
class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        
        list=[]
        if listNode==None:
            return list 
        while listNode:
            list.append(listNode.val)
            listNode=listNode.next
        return list[::-1]

'''递归实现'''
class Solution1:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        if listNode == None: 
            return [] 
        return self.printListFromTailToHead(listNode.next) + [listNode.val]

4.重建二叉树(树)

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    '''
       1.创建根节点
       2.根据前序遍历中第一个值(即为根节点的值)找到根节点在中序遍历中的位置pos
       3.根据规律找到左子树和右子树所对应的前序遍历与中序遍历的列表范围,递归建树。

    '''
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if(len(pre)==0):
            return None
        if(len(pre)==1):
            return TreeNode(pre[0])
        else:
            root=TreeNode(pre[0])
            pos=tin.index(root.val)
            root.left=self.reConstructBinaryTree(pre[1:pos+1],tin[0:pos])#数组上界不包括该值
            root.right=self.reConstructBinaryTree(pre[pos+1:],tin[pos+1:])
            return root

5.二叉树镜像(树)

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回镜像树的根节点
    '''
       根节点左右节点翻转,左右节点所对应的子树也需要翻转,递归实现
    '''
    def Mirror(self, root):
        if root !=None:
            root.left,root.right = root.right,root.left
            self.Mirror(root.left)
            self.Mirror(root.right)
        

6.用两个栈实现队列(栈和队列)

# -*- coding:utf-8 -*-
'''
A是入栈的,B是出栈的,入栈时,直接进入A即可,出栈时,先判断是否有元素,
如果B没有元素,pop肯定报错,应该先将A中所有的元素压倒B里面,再pop最上面一个元素,如果B中有就直接pop出,就可以,
这是最优的思路,两个栈实现了先进后出,在一起又实现了队列的先进先出。
'''
class Solution:
    # 初始化两个栈
    def __init__(self):
        self.stackA = []
        self.stackB = []
    # 这里只要求实现队列的push和pop操作,分别使用两个栈表示弹出和压入
    def push(self, node):
    # write code here
        self.stackA.append(node)
    def pop(self):
        if not self.stackB:
            while self.stackA:
                self.stackB.append(self.stackA.pop())
        return self.stackB.pop()

7.斐波那契数列(递归和循环)

# -*- coding:utf-8 -*-
class Solution:
    def Fibonacci(self, n):
        # write code here
        x, y = 0, 1
        if n==0:
            return 0
        if n==1:
            return 1
        while(n>1):
            x,y,n = y, x+y, n - 1
        return y

8.旋转数组的最小数字(查找和排序)

class Solution:
    '''
       比较方法:当出现前一个元素的值大于后一个元素的值时,找到分界点,旋转数组最小值为后一个元素的值。
       如果是完全旋转(12345旋转后还是12345),数组的第一个值即为旋转数组后的最小值。
    '''
    def minNumberInRotateArray(self, rotateArray):
        r_len=len(rotateArray)
        if (r_len)==0:
            return 0
        else:
            for i in range(r_len-1):
                if rotateArray[i]>rotateArray[i+1]:
                    return rotateArray[i+1]
            return rotateArray[0]
class Solution:
    '''
       二分查找:left,right为两个指针,初始时left指向0,right指向len-1;
       如果中间元素大于left指针所指向的值,则旋转数组的最小值在中间元素的右边,使left指向中间元素;   
       如果中间元素小于left指针所指向的值,则旋转数组的最小值在中间元素的左边,使right指向中间元素。
       这样,left指针始终指向前一个递增序列,right指针始终指向后一个递增序列。
       当right-left=1时,找到最小值,即为right所对应的元素。
    '''

    def minNumberInRotateArray(self, rotateArray):
        left=0
        right=len(rotateArray)-1
        mid=0
        if len(rotateArray)==0:
            return 0
        else:
            while(rotateArray[left]>=rotateArray[right]):
                if right-left==1:
                    mid=right
                    break
                mid=left+(right-left)//2
                if (rotateArray[mid]>=rotateArray[left]):
                    left=mid
                elif(rotateArray[mid]<=rotateArray[left]):
                    right=mid
            return  rotateArray[mid] 

9.跳台阶(递归与循环)

# -*- coding:utf-8 -*-
class Solution:
    '''
       此问题转化为斐波那契数列
       对于第n个台阶来说,只能从n-1或者n-2的台阶跳上来,所以F(n) = F(n-1) + F(n-2)
       初始条件 n=1:只能一种方法 n=2:两种
    '''
    def jumpFloor(self, number):
        x,y=1,2
        if number==1:
            return 1
        if number==2:
            return 2
        while (number>2):
            x,y,number=y,x+y,number-1
        return y
            

10.变态跳台阶(递归和循环)

# -*- coding:utf-8 -*-
class Solution:
    '''
       思路1:可以按照跳台阶问题的思路去思考:
       f(n)=f(n-1)+f(n-2)+...+f(n-(n-1))+f(n-n)
       f(n-1)=f(n-2)+f(n-3)+...+f(n-1-(n-2))+f(n-1-(n-1))
       f(0)=1,表示一次跳n阶,只有一种跳法。
       两式相减,可得f(n)=2*f(n-1),最后可得规律f(n)=2^(n-1)

       思路2:青蛙从0要到达第n个台阶,最后一个台阶青蛙必定要踩&#x
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值