python 剑指offer 学习之路(一)

本文精选《剑指Offer》中的经典算法题,包括斐波纳契数列、链表、二叉树、矩阵等数据结构与算法问题的解析与代码实现,提供多种解题思路。

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

斐波纳契数列

查找斐波纳契数列中第 N 个数。

所谓的斐波纳契数列是指:

前2个数是 0 和 1 。
第 i 个数是第 i-1 个数和第i-2 个数的和。
斐波纳契数列的前10个数字是:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34 …

样例
样例 1:
输入: 1
输出: 0

样例解释: 
返回斐波那契的第一个数字,是0.

样例 2:
输入: 2
输出: 1

样例解释: 
返回斐波那契的第二个数字是1.
  • 解法
    • 递归
def fibonacci(n):
    # write your code here
        res = [0, 1]
        for i in range(2, n):
            res.append(res[i-1]+res[i-2])
        return res[n-1]
  • 使用 yield 生成器
def fibonacci(n):
    # write your code here
    def fab(max):
        n,a,b=0,0,1
        while n<max:
            yield b
            a,b=b,a+b
            n=n+1
    if n == 1:
        return 0
    else:
        for i in fab(n-1):
            out = i 
        return out


print(fibonacci(2))

青蛙跳台阶

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

class Solution:
    def jumpFloor(self, number):
        # write code here
        if number == 1 or number == 2:
            return number
        jf = [1,2]
        for i in range(number-2):
            temp = jf[-1]+jf[-2]
            jf.append(temp)
        return jf[-1]

青蛙变态跳台阶

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

  • 解答:f(n)=2**(n-1)
# -*- coding:utf-8 -*-
class Solution:
    def jumpFloorII(self, number):
        # write code here
        if number <= 0:
            return 0
        else:
            return 2**(number-1)

二维数组中的查找

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

class Solution:
    # array 二维列表
    def Find(self, target, array):
        # write code here
        row = len(array) - 1
        col = len(array[0]) - 1
        i = row
        j = 0
        while j<=col and i>=0:
            if target<array[i][j]:
                i = i - 1
            elif target>array[i][j]:
                j = j + 1
            else:
                return True
        return False

替换空格

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

class Solution:
    # s 源字符串
    def replaceSpace(self, s):
        # write code here
        space = s.split(" ")
        length = len(space)
        string = str(space[0])

        for i in range(1,length):
            string = string  + "%20" + str(space[i])
        return string
  • 更简单解法
class Solution:
    # s 源字符串
    def replaceSpace(self, s):
 		return s.replace(' ','%20')

从尾到头打印链表

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

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        # write code here
        array = []
        if listNode is None:
            return array
        while listNode.next is not None:
            array.append(listNode.val)
            listNode = listNode.next
        array.append(listNode.val)
        return array[::-1] # 逆序

重建二叉树

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

# -*- 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):
        # write code here
        lon = len(pre)
        if lon == 0:
            return None
        elif lon == 1:
            return TreeNode(pre[0])
        else:
            root = TreeNode(pre[0])
            #这一步看似稍微写的有点复杂,但其实只是省了一些中间变量,pre[0]是读取的根节点,tin.index将根节点定位,那么根节点的左子树从1开始,到tin.index+1结束,建议自己在纸上将这部分框出来,就好理解的多了。
            root.left = self.reConstructBinaryTree(pre[1:tin.index(pre[0])+1],tin[:tin.index(pre[0])])
            root.right = self.reConstructBinaryTree(pre[tin.index(pre[0])+1:],tin[tin.index(pre[0])+1:])
            return root

用两个栈实现队列

题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:
事先说明这个信息:入栈时数据存入栈stackIn, 出栈时数据从stackOut弹出。执行入栈操作时,将数据源源不断的压入栈stackIn;执行出栈操作时,将stackIn的数据一次性全部弹出,存入到stackOut中。当stackOut栈非空时,不断弹出stackOut栈中的数据顺序即为队列的Pop顺序;当stackOut中的数据为空后,再将新入栈stackIn的数据一次性存入stackOut中即可。

class Solution:
    def __init__(self):
        self.stackin = []
        self.stackout = []
    def push(self, node):
        # write code here
        self.stackin.append(node)
    def pop(self):
        # return xx
        if self.stackout:
            return self.stackout.pop()
        else:
            while self.stackin:
                self.stackout.append(self.stackin.pop())
        return self.stackout.pop()

旋转数组的最小数字

题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

  • 解法1:排序
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        if not rotateArray:
            return 0
        else:
            new_array = sorted(rotateArray)
            return new_array[0]
  • 解法2:二分查找
# -*- coding:utf-8 -*-
class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        length = len(rotateArray)
        if length == 0:
            return 0
        elif length == 1:
            return rotateArray[0]
        else:
            left = 0
            right = length - 1
            while left < right:
                mid = int((left + right)/2)
                if rotateArray[mid] < rotateArray[right]:
                    right = mid
                else:
                     left = mid+1

            return rotateArray[left]

矩阵覆盖

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

# -*- coding:utf-8 -*-
class Solution:
    def rectCover(self, number):
        # write code here
        if number == 1 or number == 2 or number==0:
            return number
        else:
            first = 1
            second = 2
            for i in range(number-2):
                temp = first + second
                first = second
                second = temp
            return temp

二进制中1的个数

题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补

class Solution:
    def NumberOf1(self, n):
        # write code here
        count = 0
        if n < 0:
            n = n & 0xffffffff
        while n:
            count += 1
            n = (n - 1) & n
        return count

数值的整数次方

题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

  • 偷波懒
# -*- coding:utf-8 -*-
class Solution:
    def Power(self, base, exponent):
        # write code here
        if exponent == 0:
            return 1
        else:
            return base**exponent

调整数组顺序使奇数位于偶数前面

题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

# -*- coding:utf-8 -*-
class Solution:
    def reOrderArray(self, array):
        # write code here
        odd = []
        even = []
        if len(array)==1:
            return array
        for i in array:
            if  i % 2 == 1:
                odd.append(i)
            else:
                even.append(i)
        return odd+even

链表中倒数第k个结点

题目描述
输入一个链表,输出该链表中倒数第k个结点。

  • 解法
    p1,p2,先让p2走k-1步,然后再一起走,直到p2为最后一个 时,p1即为倒数第k个节点
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        if head==None or k<=0:
                return None
        p2=head
        p1=head
        for i in range(k-1):
            if p2.next!=None:
                p2=p2.next
            else:
                return None
        while p2.next!=None:
            p1=p1.next
            p2=p2.next
        return p1

反转链表

题目描述
输入一个链表,反转链表后,输出新链表的表头。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        if pHead==None or pHead.next==None:
            return pHead
        cur = pHead
        pre = None
        while cur != None:
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp
        return pre

内容概要:该研究通过在黑龙江省某示范村进行24小时实地测试,比较了燃煤炉具与自动/手动进料生物质炉具的污染物排放特征。结果显示,生物质炉具相比燃煤炉具显著降低了PM2.5、CO和SO2的排放(自动进料分别降低41.2%、54.3%、40.0%;手动进料降低35.3%、22.1%、20.0%),但NOx排放未降低甚至有所增加。研究还发现,经济性和便利性是影响生物质炉具推广的重要因素。该研究不仅提供了实际排放数据支持,还通过Python代码详细复现了排放特征比较、减排效果计算和结果可视化,进步探讨了燃料性质、动态排放特征、碳平衡计算以及政策建议。 适合人群:从事环境科研究的者、政府环保部门工作人员、能源政策制定者、关注农村能源转型的社会人士。 使用场景及目标:①评估生物质炉具在农村地区的推广潜力;②为政策制定者提供科依据,优化补贴政策;③帮助研究人员深入了解生物质炉具的排放特征和技术改进方向;④为企业研发更高效的生物质炉具提供参考。 其他说明:该研究通过大量数据分析和模拟,揭示了生物质炉具在实际应用中的优点和挑战,特别是NOx排放增加的问题。研究还提出了多项具体的技术改进方向和政策建议,如优化进料方式、提高热效率、建设本地颗粒厂等,为生物质炉具的广泛推广提供了可行路径。此外,研究还开发了个智能政策建议生成系统,可以根据不同地区的特征定制化生成政策建议,为农村能源转型提供了有力支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值