LeetCode刷题 _「剑指 Offer]第2版_按计划

参考链接:
剑指Offer(上)01-35题实现 python版本
剑指Offer(下)36-75题实现 Python版本

第 01 天 栈与队列(简单)

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

栈、设计、队列

class CQueue:

    def __init__(self):
        self.stack1 = []
        self.stack2 = []

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

    def deleteHead(self) -> int:
        if self.stack2:
            return self.stack2.pop()
        else:
            if self.stack1:
                while self.stack1:
                    self.stack2.append(self.stack1.pop())
                return self.stack2.pop()
            return -1

剑指 Offer 30. 包含min函数的栈

栈、设计

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stackA = []
        self.stackB = []

    def push(self, x: int) -> None:
        self.stackA.append(x)
        if not self.stackB or self.stackA[-1] <= self.stackB[-1]:
            self.stackB.append(x)

    def pop(self) -> None:
        if self.stackA.pop() == self.stackB[-1]:
            self.stackB.pop()

    def top(self) -> int:
        return self.stackA[-1]

    def min(self) -> int:
        return self.stackB[-1]

第 02 天 链表(简单)

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

栈、递归、链表、双指针

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        res = []
        while head:
            res.append(head.val)
            head = head.next
        return res[::-1]

剑指 Offer 24. 反转链表

递归、链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    # 用两个指针辅助,原链表逆转
    # 时间复杂度:O(n), 空间复杂度:O(1)
    def reverseList(self, head: ListNode) -> ListNode:
        if not head: # 边缘情况
            return None
        pre = None
        cur = head
        while cur is not None:
            next = cur.next
            cur.next = pre
            pre = cur
            cur = next
        return pre

剑指 Offer 35. 复杂链表的复制

哈希表、链表

"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""
class Solution:
    # # 深拷贝,图的深度优先搜索
    # def copyRandomList(self, head: 'Node') -> 'Node':
    #     visited = {}  # 哈希表,字典
    #     return self.dfs(head, visited)
    # def dfs(self, head, visited):
    #     if not head:
    #         return None
    #     if head in visited:
    #         return visited[head]
    #     copy = Node(head.val, None, None)
    #     visited[head] = copy
    #     copy.next = self.dfs(head.next, visited) # 先复制next结点
    #     copy.random = self.dfs(head.random, visited) # 再复制random结点
    #     return copy

    # # 深拷贝,图的广度优先搜索
    # def copyRandomList(self, head: 'Node') -> 'Node':
    #     visited = {}  # 哈希表,字典
    #     return self.bfs(head, visited)
    # def bfs(self, head, visited):
    #     if not head:
    #         return None
    #     copy = Node(head.val, None, None) # 创建新的结点
    #     queue = []  # 利用队列记录
    #     queue.append(head)
    #     visited[head] = copy
    #     while queue:
    #         node = queue.pop(0)
    #         if node.next and node.next not in visited:
    #             visited[node.next] = Node(node.next.val, None, None)
    #             queue.append(node.next)
    #         if node.random and node.random not in visited:
    #             visited[node.random] = Node(node.random.val, None, None)
    #             queue.append(node.random)
    #         visited[node].next = visited.get(node.next, None)
    #         visited[node].random = visited.get(node.random, None)
    #     return copy
    
    # 迭代这种方法比较直接,就是分别拷贝next结点和random结点。
    def copyRandomList(self, head: 'Node') -> 'Node':
        visited = {
   }  #构建一个链表来记录
        def getCloneNode(node):
            if node:
                if node not in visited:
                    visited[node] = Node(node.val, None, None)
                    return visited[node]                
                else:
                    return visited[node]
          
        if not head:
            return head
        old_node = head
        new_node = Node(old_node.val, None, None)
        visited[old_node] = new_node
        
        while old_node:
            new_node.next = getCloneNode(old_node.next)
            new_node.random = getCloneNode(old_node.random)
            old_node = old_node.next
            new_node = new_node.next
            
        return visited[head]

第 03 天 字符串(简单)

剑指 Offer 05. 替换空格

字符串

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

剑指 Offer 58 - II. 左旋转字符串

数学、双指针、字符串

class Solution:
    # 字符串切片
    def reverseLeftWords(self, s: str, n: int) -> str:
        s1 = s[:n]
        s2 = s[n:]
        return s2 + s1

    # # 旋转操作
    # def reverseLeftWords(self, s: str, n: int) -> str:
    #     s = list(s)  # 因为字符串是不可变序列,还有元组
    #     length = len(s) - 1
    #     self.reverse(s, 0, n - 1)
    #     self.reverse(s, n, length)
    #     self.reverse(s, 0, length)
    #     return "".join(s)

    # def reverse(self, s, start, end):
    #     while start < end:
    #         s[start], s[end] = s[end], s[start]
    #         start += 1
    #         end -= 1

第 04 天 查找算法(简单)

剑指 Offer 03. 数组中重复的数字

数组、哈希表、排序

class Solution:
    def findRepeatNumber(self, nums: List[int]) -> int:
        res = collections.Counter(nums)
        for key in res:
            if res[key] > 1:
                return key

剑指 Offer 53 - I. 在排序数组中查找数字 I

数组、二分查找

class Solution:
    # # 二分查找,找是target的值的位置
    # def search(self, nums: List[int], target: int) -> int:
    #     left, right = 0, len(nums) - 1
    #     res = 0
    #     while left <= right:
    #         m = (left + right) // 2
    #         if nums[m] == target: # 若找到目标值后,从中心扩散,寻找上下界
    #             res += 1
    #             i = m - 1
    #             j = m + 1
    #             while j <= len(nums) - 1 and nums[j] == target:
    #                 res += 1
    #                 j += 1
    #             while i >= 0 and nums[i] == target:
    #                 res += 1
    #                 i -= 1
    #             break
    #         elif nums[m] < target:
    #             left = m + 1
    #         else:
    #             right = m - 1
    #     return res

    # 二分查找,相当于找左右边界,找不是target的值的位置
    def search(self, nums: List[int], target: int) -> int:
        i, j = 0, len(nums) - 1
        while i <= j:
            m = (i + j) // 2
            if nums[m] <= target: # i想找的是第一个大于target的数
                i = m + 1
            else:
                j = m - 1
        right = i  # 找右边界 

        i, j = 0, len(nums) - 1
        while i <= j:
            m = (i + j) // 2
            if nums[m] < target: 
                i = m + 1  # 尝试查找比target小的更大的数
            else: # j想找的是第一个小于target的数
                j = m - 1  # 尝试查找大于等于target的更小的数
        left = j  # 找左边界
        
        return right - left - 1

剑指 Offer 53 - II. 0~n-1中缺失的数字

位运算、数组、哈希表、数学

class Solution:
    # 二分查找
    def missingNumber(self, nums: List[int]) -> int:
        i, j = 0, len(nums) - 1
        while i <= j:
            mid = (i + j) // 2
            if nums[mid] == mid:
                i = mid + 1
            else:
                j = mid - 1
        return i

第 05 天 查找算法(中等)

剑指 Offer 04. 二维数组中的查找

数组、二分查找、分治、矩阵

class Solution:
    # 二分查找,使得每一次都可以分出两个相反的选择。
    def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        if not matrix:  # 考虑边界情况,特殊情况
            return False
        n, m = len(matrix), len(matrix[0]) # 从右上角开始,大的往下找,小的往左找
        i, j = 0, m - 1
        while 0 <= i < n and 0 <= j < m:
            if matrix[i][j] == target:
                return True
            elif matrix[i][j] < target:
                i += 1
            else:
                j -= 1
        return False

剑指 Offer 11. 旋转数组的最小数字

数组、二分查找

class Solution:
    # 部分有序,二分查找。找出右排序数组中的第一个数字,也就是旋转点
    # 时间复杂度:O(log2N), 空间复杂度:O(1)
    def minArray(self, numbers: List[int]) -> int:
        i, j = 0 , len(numbers) - 1
        while i < j:  # 已知j一定在右排序数组中
            m = (i + j) // 2  # 当前的中心点
            if numbers[m] > numbers[j]: i = m + 1  # 若右侧的点小于中心位置的点,m一定在左排序区间内,则说明旋转点一定在中心位置的右侧
            elif numbers[m] < numbers[j]: j = m  # 若右侧的点大于中心位置的点,m一定在右排序区间内,则说明旋转点一定在中心位置的左侧
            else: j = j - 1   # 若相等,则需要进一步判断, 可参考某大佬评论
            '''
            若旋转点 x < j, 则上述肯定往左区间找
           若旋转点 x = j, 则容易错过旋转点,但可以证明,nums[i]=nums[x]=nums[中心点]=...=nums[j],则最终当i=j时返回的num[i]值等于旋转点的值
            还有不用nums[m] 和 nums[i]做比较,因为无法判断 m 在哪个排序数组中
            本质上,是因为 j 初始值肯定在右排序数组中; i 初始值无法确定在哪个排序数组中。
            对于以下两示例,当 i = 0, j = 4, m = 2 时,有 nums[m] > nums[i] ,而结果不同。
            [1, 2, 3, 4, 5] 旋转点 x = 0: m 在右排序数组(此示例只有右排序数组);
            [3, 4, 5, 1, 2] 旋转点 x = 3: m 在左排序数组。
            '''
        return numbers[i]

剑指 Offer 50. 第一个只出现一次的字符

队列、哈希表、字符串、计数

class Solution:
    # 利用哈希特征来进行高效查找
    def firstUniqChar(self, s: str) -> str:
        if not s:
            return " "
        haxi = dict()
        for num in s:
            if num in haxi: haxi[num] += 1
            else: haxi[num] = 1
        for num in haxi:
            if haxi[num] == 1:
                return num
        return " "

第 06 天 搜索与回溯算法(简单)

剑指 Offer 32 - I. 从上到下打印二叉树

树、广度优先搜索、二叉树

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

class Solution:
    # # 二叉树的层次遍历,用队列
    # def levelOrder(self, root: TreeNode) -> List[int]:
    #     if root is None:
    #         return []
    #     queue1, queue2, res = [], [], []
    #     queue1.append(root)
    #     while queue1:
    #         node = queue1.pop(0)
    #         res.append(node.val)
    #         if node.left:
    #             queue2.append(node.left)
    #         if node.right:
    #             queue2.append(node.right)
    #         if len(queue1) == 0:
    #             queue1 = queue2
    #             queue2 = []
    #     return res

     # 二叉树的层次遍历,用队列
    def levelOrder(self, root: TreeNode) -> List[int]:
        if root is None:
            return []
        queue, res = [], []
        queue.append(root)
        while queue:
            node = queue.pop(0)
            res.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        return res

剑指 Offer 32 - II. 从上到下打印二叉树

树、广度优先搜索、二叉树

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

class Solution:
    # 层次遍历,队列
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if root is None:
            return []
        queue1, queue2, res, temp = [], [], [], []
        queue1.append(root)
        while queue1:
            node = queue1.pop(0)
            temp.append(node.val)
            if node.left:
                queue2.append(node.left)
            if node.right:
                queue2.append(node.right)
            if len(queue1) == 0:
                res.append(temp)
                temp = []
                queue1 = queue2
                queue2 = []
        return res

剑指 Offer 32 - III. 从上到下打印二叉树

树、广度优先搜索、二叉树

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

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if root is None:
            return []
        queue1, queue2, res, temp, count = [], [], [], [], 0
        queue1.append(root)
        while queue1:
            node = queue1.pop(0)
            temp.append(node.val)
            if node.left:
                queue2.append(node.left)
            if node.right:
                queue2.append(node.right)
            if len(queue1) == 0:
                if count % 2 == 0:
                    res.append(temp)
                    temp = []
                else:
                    res.append(temp[::-1])
                    temp = []
                count += 1
                queue1 = queue2
                queue2 = []
        return res

第 07 天 搜索与回溯算法(简单)

剑指 Offer 26. 树的子结构

树、深度优先搜索、二叉树

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

class Solution:
    # 深度优先遍历,递归
    def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
        if A == None or B == None:
            return False
        return self.dfs(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B)
    
    def dfs(self, A, B):
        if B == None:
            return True
        if A == None:
            return False
        return A.val == B.val and self.dfs(A.left, B.left) and self.dfs(A.right, B.right)

剑指 Offer 27. 二叉树的镜像

树、深度优先搜索、广度优先搜索

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

class Solution:
    # # 递归实现
    # def mirrorTree(self, root: TreeNode) -> TreeNode:
    #     if root == None:
    #         return None
    #     if root.left != None or root.right != None: # 交换左右子树
    #         root.left, root.right = root.right, root.left
    #         self.mirrorTree(root.left)
    #         self.mirrorTree(root.right)
    #     return root

    # 迭代实现, 用栈实现
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        stack 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值