[剑指Offer]05~08

[剑指Offer]05~08

学习使用工具

剑指Offer http://itmyhome.com/sword-means-offer/sword-means-offer.pdf

LeetCode的剑指Offer题库 https://leetcode.cn/problemset/all/

本节阅读文章

https://blog.csdn.net/sinat_28576553/article/details/84404653

剑指Offer 05:替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1:

输入:s = "We are happy."
输出:"We%20are%20happy."

限制:

0 <= s 的长度 <= 10000

解法:

这么简单的题?难道有什么陷阱?然后半分钟就写完了,真的没有什么陷阱。

def replaceSpace(self, s: str) -> str:
        ans = ""
        for i in s:
            if i == " ":
                ans = ans + "%20"
            else:
                ans = ans + i
        return ans

更加简单的一行写法:

def replaceSpace(self, s: str) -> str:
        return s.replace(" ","%20");

剑指Offer 06. 从尾到头打印链表

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

示例:

输入:head = [1,3,2]
输出:[2,3,1]

限制:

0 <= 链表长度 <= 10000

解法:

递归,递归!递归到链表最尾端,将此处的节点值加入结果数组;之后逐层退出递归,重复这个过程。

def reversePrint(self, head: ListNode) -> List[int]:
        ans = []
        if not head:
            return ans

        def reverse(head: ListNode):
            if head:
                reverse(head.next)
                ans.append(head.val)

        reverse(head)
        return ans

然后发现还有更简单的写法:直接遍历一遍链表加入数组,倒序输出数组即可。

def reversePrint(self, head: ListNode) -> List[int]:
        ans = []
        while(head):
            ans.append(head.val)
            head = head.next

        return ans[::-1]

这里正好复习一下Python的数组切片使用方法。

切片使用2个冒号分隔的3个数字来完成:

  • 第一个数字表示切片的开始位置,默认为0;
  • 第二个数字表是切片的截止(但不包含)位置,默认为列表长度;
  • 第三个数字表示切片的步长,默认为1。当步长省略时,可以省略第2个冒号。
aList=[3,4,5,6,7,9,11,13,15,17]
print(aList[::])  #[3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
print(aList[::-1])  #[17, 15, 13, 11, 9, 7, 6, 5, 4, 3],倒序输出
print(aList[::2])  # [3, 5, 7, 11, 15], 以步长为2进行输出
print(aList[1::2])  #[4, 6, 9, 13, 17], 从1开始步长为2
print(aList[3::])  #[6, 7, 9, 11, 13, 15, 17]
print(aList[3:6])  #[6, 7, 9],省略的是步长,输出位置在[3,6)的元素

剑指Offer 07:重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

示例 1:

https://assets.leetcode.com/uploads/2021/02/19/tree.jpg

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

示例 2:

Input: preorder = [-1], inorder = [-1]
Output: [-1]

限制:

0 <= 节点个数 <= 5000

解法:

先来复习一下从前序&中序遍历重建原始二叉树的算法流程。

  • 前序遍历结构:根节点→左子树→右子树
  • 中序遍历结构:左子树→根节点→右子树
  • 前序遍历首位必然为根节点
  • 中序遍历中,根节点之前被遍历到的为根节点左子树,根节点之后被遍历到的为根节点右子树

又是递归,脑内模拟的很好,实际写起来还是有点绕的。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:       
        if not preorder:  # 判空
            return None
        
        length = len(preorder) # 获取数组长度
        rot = preorder[0] # 获取根节点值
       
        temp = 0 # 记录根节点在中序遍历中的位置
        for i in range(length):
            if inorder[i] == rot: # 在中序遍历中找到根节点,记录位置,更新temp
                temp = i
                break

        root = TreeNode(rot) # 以rot为值,建立根节点
        preleft = preorder[1 : temp + 1] # 截取前序遍历中的:左子树
        preright = preorder[temp + 1 : length] # 截取前序遍历中的:右子树
   
        inleft = inorder[0 : temp] # 截取中序遍历中的:左子树
        inright = inorder[temp + 1 : length] #截取中序遍历中的:右子树

        root.left = self.buildTree(preleft,inleft) # 递归建立左子树
        root.right = self.buildTree(preright,inright) # 递归建立右子树

        return root

疑惑,LeetCode上的剑指Offer题单直接从07跳到09了,没有08

剑指Offer 09:用两个栈实现队列

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTaildeleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

示例 1:

输入:
["CQueue","appendTail","deleteHead","deleteHead","deleteHead"]
[[],[3],[],[],[]]
输出:[null,null,3,-1,-1]

示例 2:

输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]

提示:

  • 1 <= values <= 10000
  • 最多会对appendTail、deleteHead进行 10000 次调用

解法:

又是简单题。两个栈分别看作是队尾和队头,进栈元素暂时保留在队尾。

需要出栈时,先判定队头空不空

  • 如果空的话就将队尾栈全部pop进队头栈,再从队头栈出栈
  • 如果不空直接从队头栈出栈即可
class CQueue:

    def __init__(self):
        self.Head = []
        self.Tail = []

    def appendTail(self, value: int) -> None:
        self.Tail.append(value)

    def deleteHead(self) -> int:
        if not self.Head:
            if not self.Tail:
                return -1
            while(self.Tail):
                self.Head.append(self.Tail.pop())
            return self.Head.pop()
        else:
            return self.Head.pop()
posted @ 2023-03-06 14:06  无机呱子  阅读(13)  评论(0编辑  收藏  举报