二刷剑指offer-- 01.02.03.04.05.06.07.08.09

本文深入解析了一系列经典算法问题,包括二维数组查找、字符串空格替换、链表逆序输出、二叉树重建、栈实现队列、斐波那契数列、跳跃台阶问题及二进制位运算等,提供了多种解决思路,如递归、循环和数据结构应用。

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

01题目描述

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

思路一暴力破解法:
每一行看看在在里面即可

思路二:从左下角走起:

class Solution:
    # array 二维列表
    #从左下角元素往上查找,右边元素是比这个元素大,上边是的元素比这个元素小。
    #于是,target比这个元素小就往上找,比这个元素大就往右找。如果出了边界,
    #则说明二维数组中不存在target元素。
    def Find(self, target, array):
        row = len(array)-1
        col = len(array[0])-1
        L_row = row
        L_col = 0
        while L_row <=row and L_row >= 0 and L_col >= 0 and L_col <= col:
            if  target < array[L_row][L_col]:
                L_row -=1
            elif  target > array[L_row][L_col]:
                L_col +=1
            else:
                return True
        return False     

02:
替换空格

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

用python的字符串的replace即可

03:
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

思路1:
读完全部的数值,放到我们的list中然后用list.reverse()

class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        all_numbers = []
        while listNode:
            all_numbers.append(listNode.val)
            listNode = listNode.next
        all_numbers.reverse()    
        return  all_numbers 

思路2:

递归的思想:走到头,然后输出数值, 递归的思想比较重要在这道题,上面的思想只是python技巧。

class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def __init__(self):
        self.xixi = []
    def printListFromTailToHead(self, listNode):
        if listNode is None:
            return []
        self.printListFromTailToHead(listNode.next)
        self.xixi.append(listNode.val)
        return self.xixi

04 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

基本知识点。
1.树的遍历,前序遍历是中左右,中序遍历是左中右,体会一句话,这里是正对每颗子树的操作。

在这里插入图片描述

思路:
递归实现:
前序遍历可以知道从上到下的每个结点
后序遍历可以知道这个结点的左右子树成分
同归递归走到最后面的时候,进行返回即可。

class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        if len(pre) == 0:
            return None
        if len(pre) == 1:
            return TreeNode(pre[0])
            #走到最后了进行判断并且开始有返回
        else:
            node = TreeNode(pre[0])
            node.left = self.reConstructBinaryTree(pre[1:tin.index(pre[0])+1],tin[:tin.index(pre[0])]) 
            #左子树的话,通过   
            node.right = self.reConstructBinaryTree(pre[tin.index(pre[0])+1:],tin[tin.index(pre[0])+1:]) 
        return node

05.用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

栈: 先进后出的
队列 :先进先出

思路1:跳开题目本身,用list来实现队列, 用一个列表即可啦。

class Solution:
    def __init__(self):
        self.line = []
    def push(self, node):
        self.line.append(node)
        # write code here
    def pop(self):
        out = self.line.pop(0)
        return out  

思路2:真的用两个栈呢?这时候我们假设列表是没有pop() 只有pop(). 那么列表在这里就变成了只有栈的功能了

一个栈用来放东西的。一个栈用来出东西的,首先是存进去,然后如果有要出来,那么将放东西的栈全部放到出东西的栈里面,但是放之前要确认这个栈是否为空,如果不为空,那么就出,出完了在放。

class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
    def push(self, node):
        self.stack1.append(node)
        # write code here
    def pop(self):
        if self.stack2 != []:
            out = self.stack2.pop() 
        else:
            while self.stack1:
                stack1_out = self.stack1.pop()
                self.stack2.append(stack1_out)
            out = self.stack2.pop()   
        return out  
        # return xx

06.斐波那契数列
(从0开始,第0项为0)。n<=39
斐波那契数列:第三项开始是前两项之和。

思路1:

递归的细想:但是时间上会爆掉.
学习的点:
1.递归一般都很美,格式上写的很美
2.使用递归的时候要清楚几个点:
1.有去有回,所以要走到低看看需要什么,这里的话就是走到底会给出,三个不同的结果。0,1,2 所以这里用了if 和return,用来表示到底了。然后并列给出最后的结果。
2.目标是什么,也就是我们function本身的目的,这里非常简单就是返回一个最终的结果,该结果是递归得到的,前两个数的和就是我们的结果,然后就最终给出了递归的结果啦。

class Solution:
    def Fibonacci(self, n):
        if n==0:
            return 0
        if n==1:
            return 1
        if n==2:
            return 1
        return self.Fibonacci(n-1) + self.Fibonacci(n-2)
        # write code here

思路2:

循环的思想:递推的细想。

class Solution:
    def Fibonacci(self, n):
        stack = [0,1,1]
        
        if n >2:
            for i in range(3,n+1): 
                stack.append(stack[i-1]+stack[i-2])
        return stack[n]

跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果

递归的思想:
n 阶台阶的情况:来自于什么,可能来自第n-1过来的, 也可能是来自第n-1过来的。f(n) 表示多少种跳法。f(n) = f(n-1)+f(n-2) 所以是递归的细想,好好琢磨下。和刚刚一样,首先递归到了头,应该做什么?

还是一样:,美丽的递归,但是有缺点的递归。
1.递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间。->效率

2.递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算,如fibonacci斐波那契数列的递归实现。->效率

3.调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。->性能

递归:
    class Solution:
        def jumpFloor(self, number):
            if number ==1:
                return 1
            if number ==2:
                return 2
            return self.jumpFloor(number-1)+self.jumpFloor(number-2)
循环
    class Solution:
        def jumpFloor(self, number):
            stack = [0,1,2]
            if number >2:
                for i in range(3,number+1): 
                    stack.append(stack[i-1]+stack[i-2])
            return stack[number]

循环的思想看上面的就OK了,改点东西就可以。

08.变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

这一次不在限制了,上一题的区别是什么?没什么区别,不过就是我们这次开始要把前面全部算一次和。

class Solution:
    def jumpFloorII(self, number):
        stack = [0,1,2]
        if number >2:
            for i in range(3,number+1): 
                stack.append(sum(stack)+1) 
                #加一是包括自己的那一种可能,之前是不算上自己的可能性的
        return stack[number]

09.矩形覆盖

我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

做这种题目:思路先举例子,然后看看有没有规律,有规律就把规律用代码实现
比如n =1 ,1
比如n =2 ,2
比如n=3 ,3
比如n=4,5

和上面一样斐波那契数列的应用

10.二进制中1的个数
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

在这里插入图片描述

思路一:使用python 的自带bin(),但是负数部分并没有按照补码计算,所以现在这里会加上负数部分处理。然后负数部分也是通过规律发现了从右边数起,遇到第一个1的左边部分全部反转。所以最终得到了结果。

class Solution:
    def NumberOf1(self, n):
        if n >= 0:
            c = bin(n).count('1')
            return c
        else:
            original = bin(abs(n)).lstrip('0b')
            d_list =list(original)
            d_list.reverse()
            c = d_list[d_list.index('1'):].count('1')
            return c+(32 - len(d_list))    
        # write code here

class Solution:
    def NumberOf1(self, n):
        if n >= 0:
            c = bin(n).count('1')
            return c
        else:
            c = bin(n & 0xffffffff).count('1')
            return c  
        # write code here

思路二:正常脑回路,计算法,先是看看

  1. 数字与1相与可以得到最低位
  2. 所以可以用来统计1的个数,因为每一次的迭代都需要遇到最终的1
    举例来说,6的二进制是 110 ,6-1=5的二进制是 101,6&5=100, 如此操作之后6中原来的110变为100,循环计数统计1的个数,直至n变为0为止
    在这里插入图片描述
    3.负数呢

在这里插入图片描述

class Solution:
    def NumberOf1(self, n):
        count = 0
        if n < 0:
            n = n &0xffffffff
        while n:
            count +=1
            n &=(n-1)
        return count    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值