跳转至

LeetCode 题目

在 LeetCode 刷题过程中,掌握常见的算法题型和实现方法非常重要。以下是几道常见的 LeetCode 题目及其 Python 实现,涵盖数组、链表、动态规划等不同领域的算法。

1. 两数之和(Two Sum)

题目:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回它们的数组下标。

LeetCode 链接两数之和

Python 实现

def two_sum(nums, target):
    hash_map = {}
    for i, num in enumerate(nums):
        complement = target - num
        if complement in hash_map:
            return [hash_map[complement], i]
        hash_map[num] = i

# 使用示例
nums = [2, 7, 11, 15]
target = 9
print(two_sum(nums, target))  # 输出: [0, 1]

详解

  • 使用哈希表记录数组元素及其索引,通过检查 target - num 是否在哈希表中,时间复杂度为 O(n),空间复杂度为 O(n)。

2. 盛最多水的容器(Container With Most Water)

题目:给定一个数组 height,其中每个元素表示一个垂直线的高度。找出两条线所围成的容器可以盛最多的水。

LeetCode 链接盛最多水的容器

Python 实现

def max_area(height):
    l, r = 0, len(height) - 1
    max_area = 0
    while l < r:
        max_area = max(max_area, min(height[l], height[r]) * (r - l))
        if height[l] < height[r]:
            l += 1
        else:
            r -= 1
    return max_area

# 使用示例
height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
print(max_area(height))  # 输出: 49

详解

  • 使用双指针法,逐步移动左右两端,计算并更新当前最大面积。时间复杂度为 O(n)。

3. 三数之和(3Sum)

题目:给定一个包含 n 个整数的数组,判断数组中是否存在三个元素,使得它们的和为零。找出所有满足条件且不重复的三元组。

LeetCode 链接三数之和

Python 实现

def three_sum(nums):
    nums.sort()
    res = []
    for i in range(len(nums) - 2):
        if i > 0 and nums[i] == nums[i - 1]:
            continue
        l, r = i + 1, len(nums) - 1
        while l < r:
            s = nums[i] + nums[l] + nums[r]
            if s < 0:
                l += 1
            elif s > 0:
                r -= 1
            else:
                res.append([nums[i], nums[l], nums[r]])
                while l < r and nums[l] == nums[l + 1]:
                    l += 1
                while l < r and nums[r] == nums[r - 1]:
                    r -= 1
                l += 1
                r -= 1
    return res

# 使用示例
nums = [-1, 0, 1, 2, -1, -4]
print(three_sum(nums))  # 输出: [[-1, -1, 2], [-1, 0, 1]]

详解

  • 先将数组排序,使用双指针技巧找出三元组。时间复杂度为 O(n²)。

4. 删除排序数组中的重复项(Remove Duplicates from Sorted Array)

题目:给定一个有序数组 nums,你需要原地删除其中的重复元素,使得每个元素只出现一次,返回删除后数组的新长度。

LeetCode 链接删除排序数组中的重复项

Python 实现

def remove_duplicates(nums):
    if not nums:
        return 0
    i = 0
    for j in range(1, len(nums)):
        if nums[j] != nums[i]:
            i += 1
            nums[i] = nums[j]
    return i + 1

# 使用示例
nums = [1, 1, 2]
print(remove_duplicates(nums))  # 输出: 2,nums 数组变为 [1, 2]

详解

  • 使用双指针法,一个指针 i 指向当前去重的最后一个元素,另一个指针 j 遍历整个数组。时间复杂度为 O(n),空间复杂度为 O(1)。

5. 二叉树的最大深度(Maximum Depth of Binary Tree)

题目:给定一个二叉树,找出其最大深度。

LeetCode 链接二叉树的最大深度

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def max_depth(root):
    if not root:
        return 0
    left_depth = max_depth(root.left)
    right_depth = max_depth(root.right)
    return max(left_depth, right_depth) + 1

# 使用示例
root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20, TreeNode(15), TreeNode(7))
print(max_depth(root))  # 输出: 3

详解

  • 使用递归法计算每个节点的最大深度。时间复杂度为 O(n),空间复杂度为 O(h),其中 n 为节点总数,h 为树的高度。

6. 斐波那契数列(Fibonacci Sequence)

题目:求解斐波那契数列的第 n 项。

LeetCode 链接斐波那契数列

Python 实现

def fib(n):
    if n <= 1:
        return n
    a, b = 0, 1
    for _ in range(2, n + 1):
        a, b = b, a + b
    return b

# 使用示例
n = 10
print(fib(n))  # 输出: 55

详解

  • 通过迭代法优化递归方式,避免重复计算。时间复杂度为 O(n),空间复杂度为 O(1)。

以下是更多经典的 LeetCode 题目及其 Python 实现,涵盖更多常见算法和数据结构,包括动态规划、二叉树、回溯、贪心算法等。

7. 爬楼梯(Climbing Stairs)

题目:假设你正在爬楼梯。需要 n 阶才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶?

LeetCode 链接Climbing Stairs

Python 实现

def climb_stairs(n):
    if n == 1:
        return 1
    a, b = 1, 2
    for i in range(3, n + 1):
        a, b = b, a + b
    return b

# 使用示例
n = 5
print(climb_stairs(n))  # 输出: 8

详解

  • 这是经典的动态规划问题,类似于斐波那契数列。每一步的选择可以通过前两步来决定。时间复杂度为 O(n),空间复杂度为 O(1)。

8. 组合总和(Combination Sum)

题目:给定一个无重复元素的数组 candidates 和一个目标数 target,找出 candidates 中所有可以使数字和为 target 的组合。

LeetCode 链接Combination Sum

Python 实现

def combination_sum(candidates, target):
    res = []
    def dfs(start, path, target):
        if target == 0:
            res.append(path)
            return
        for i in range(start, len(candidates)):
            if candidates[i] <= target:
                dfs(i, path + [candidates[i]], target - candidates[i])

    dfs(0, [], target)
    return res

# 使用示例
candidates = [2, 3, 6, 7]
target = 7
print(combination_sum(candidates, target))  # 输出: [[2, 2, 3], [7]]

详解

  • 使用深度优先搜索(DFS)来递归查找所有组合。每次从当前数字开始递归,避免重复选择。时间复杂度较高,取决于输入大小和解空间。

9. 最大子序和(Maximum Subarray)

题目:给定一个整数数组 nums,找到一个具有最大和的连续子数组,返回其最大和。

LeetCode 链接Maximum Subarray

Python 实现

def max_sub_array(nums):
    max_sum = curr_sum = nums[0]
    for num in nums[1:]:
        curr_sum = max(num, curr_sum + num)
        max_sum = max(max_sum, curr_sum)
    return max_sum

# 使用示例
nums = [-2,1,-3,4,-1,2,1,-5,4]
print(max_sub_array(nums))  # 输出: 6

详解

  • 使用动态规划的思想,每次选择当前元素或者与前面的子数组相加,来获得当前最大和。时间复杂度为 O(n)。

10. 不同路径(Unique Paths)

题目:一个机器人位于 m x n 网格的左上角。机器人每次只能向下或者向右移动一步,机器人试图达到网格的右下角。计算共有多少条不同的路径。

LeetCode 链接Unique Paths

Python 实现

def unique_paths(m, n):
    dp = [[1] * n for _ in range(m)]
    for i in range(1, m):
        for j in range(1, n):
            dp[i][j] = dp[i-1][j] + dp[i][j-1]
    return dp[-1][-1]

# 使用示例
m, n = 3, 7
print(unique_paths(m, n))  # 输出: 28

详解

  • 这是一个典型的动态规划问题。使用二维数组 dp 来存储到达每个位置的路径数,结果为右下角的路径数。时间复杂度为 O(m * n)。

11. 买卖股票的最佳时机(Best Time to Buy and Sell Stock)

题目:给定一个数组 prices,其中 prices[i] 是一支股票第 i 天的价格。你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

LeetCode 链接Best Time to Buy and Sell Stock

Python 实现

def max_profit(prices):
    min_price = float('inf')
    max_profit = 0
    for price in prices:
        min_price = min(min_price, price)
        max_profit = max(max_profit, price - min_price)
    return max_profit

# 使用示例
prices = [7, 1, 5, 3, 6, 4]
print(max_profit(prices))  # 输出: 5

详解

  • 这是一个贪心算法问题。我们通过遍历找到最低的买入价格,并计算当前价格与最低价格之间的差值作为可能的最大利润。时间复杂度为 O(n)。

12. 岛屿数量(Number of Islands)

题目:给定一个由 '1'(陆地)和 '0'(水)组成的二维网格,计算岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平和垂直方向上相邻的陆地连接。

LeetCode 链接Number of Islands

Python 实现

def num_islands(grid):
    if not grid:
        return 0

    def dfs(i, j):
        if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] == '0':
            return
        grid[i][j] = '0'
        dfs(i-1, j)
        dfs(i+1, j)
        dfs(i, j-1)
        dfs(i, j+1)

    count = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == '1':
                dfs(i, j)
                count += 1
    return count

# 使用示例
grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
print(num_islands(grid))  # 输出: 1

详解

  • 使用深度优先搜索(DFS)来遍历所有陆地,将相连的陆地标记为水。时间复杂度为 O(m * n),其中 m 是行数,n 是列数。

13. 全排列(Permutations)

题目:给定一个没有重复数字的序列,返回所有可能的全排列。

LeetCode 链接Permutations

Python 实现

def permute(nums):
    res = []
    def backtrack(path, used):
        if len(path) == len(nums):
            res.append(path[:])
            return
        for i, num in enumerate(nums):
            if used[i]:
                continue
            path.append(num)
            used[i] = True
            backtrack(path, used)
            path.pop()
            used[i] = False

    backtrack([], [False] * len(nums))
    return res

# 使用示例
nums = [1, 2, 3]
print(permute(nums))  # 输出: [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

详解

  • 使用回溯法生成所有排列,通过递归和状态回溯来构建全排列。时间复杂度为 O(n!)。

继续深入一些经典 LeetCode 题目及其 Python 实现,涉及更多领域和复杂度的题目。这些题目包括回溯算法、贪心算法、图算法等。

14. 组合总和 II(Combination Sum II)

题目:给定一个包含 n 个整数的数组 candidates 和一个目标数 target,找出 candidates 中所有可以使数字和为 target 的组合。每个组合中的数字可以使用多次,但每个数字在组合中只能出现一次。

LeetCode 链接Combination Sum II

Python 实现

def combination_sum2(candidates, target):
    res = []
    candidates.sort()

    def backtrack(start, path, target):
        if target == 0:
            res.append(path[:])
            return
        for i in range(start, len(candidates)):
            if i > start and candidates[i] == candidates[i - 1]:
                continue
            if candidates[i] > target:
                break
            path.append(candidates[i])
            backtrack(i + 1, path, target - candidates[i])
            path.pop()

    backtrack(0, [], target)
    return res

# 使用示例
candidates = [10, 1, 2, 7, 6, 5]
target = 8
print(combination_sum2(candidates, target))  # 输出: [[1, 2, 5], [1, 7], [2, 6]]

详解

  • 使用回溯法来生成所有组合。排序数组可以帮助我们更快地剪枝。避免重复组合的方法是跳过相同的元素。时间复杂度为 O(2^n)。

15. 合并区间(Merge Intervals)

题目:给定一个区间的集合,合并所有重叠的区间。

LeetCode 链接Merge Intervals

Python 实现

def merge(intervals):
    if not intervals:
        return []

    intervals.sort(key=lambda x: x[0])
    merged = [intervals[0]]

    for current in intervals[1:]:
        last_merged = merged[-1]
        if current[0] <= last_merged[1]:
            last_merged[1] = max(last_merged[1], current[1])
        else:
            merged.append(current)

    return merged

# 使用示例
intervals = [[1,3],[2,6],[8,10],[15,18]]
print(merge(intervals))  # 输出: [[1, 6], [8, 10], [15, 18]]

详解

  • 首先将区间按起始位置排序,然后遍历区间,合并重叠部分。时间复杂度为 O(n log n)。

16. 单词拆分 II(Word Break II)

题目:给定一个字符串 s 和一个字典 wordDict,请你将 s 拆分成若干个词汇,并返回所有可能的拆分结果。

LeetCode 链接Word Break II

Python 实现

def word_break(s, word_dict):
    memo = {}

    def backtrack(start):
        if start in memo:
            return memo[start]
        if start == len(s):
            return [[]]

        res = []
        for end in range(start + 1, len(s) + 1):
            if s[start:end] in word_dict:
                for sub_sentence in backtrack(end):
                    res.append([s[start:end]] + sub_sentence)

        memo[start] = res
        return res

    word_dict = set(word_dict)
    return [' '.join(words) for words in backtrack(0)]

# 使用示例
s = "catsanddog"
word_dict = ["cat", "cats", "and", "sand", "dog"]
print(word_break(s, word_dict))  # 输出: ["cat sand dog", "cats and dog"]

详解

  • 使用回溯法结合记忆化搜索来处理子问题。时间复杂度较高,但通过记忆化减少重复计算。时间复杂度为 O(2^n)。

17. 最长递增子序列(Longest Increasing Subsequence)

题目:给定一个无序整数数组,找到其中最长递增子序列的长度。

LeetCode 链接Longest Increasing Subsequence

Python 实现

def length_of_lis(nums):
    if not nums:
        return 0

    dp = [1] * len(nums)
    for i in range(1, len(nums)):
        for j in range(i):
            if nums[i] > nums[j]:
                dp[i] = max(dp[i], dp[j] + 1)

    return max(dp)

# 使用示例
nums = [10, 9, 2, 5, 3, 7, 101, 18]
print(length_of_lis(nums))  # 输出: 4

详解

  • 使用动态规划来解决这个问题。时间复杂度为 O(n^2)。可以通过二分查找优化到 O(n log n)。

18. 图的最短路径(Shortest Path in a Graph)

题目:给定一个带权图,找出从起点到终点的最短路径。

LeetCode 链接Shortest Path in a Graph

Python 实现(Dijkstra 算法)

import heapq

def shortest_path(grid):
    rows, cols = len(grid), len(grid[0])
    directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]

    def in_bounds(x, y):
        return 0 <= x < rows and 0 <= y < cols

    pq = [(0, 0, 0)]  # (cost, x, y)
    dist = [[float('inf')] * cols for _ in range(rows)]
    dist[0][0] = 0

    while pq:
        cost, x, y = heapq.heappop(pq)
        if x == rows - 1 and y == cols - 1:
            return cost
        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if in_bounds(nx, ny):
                new_cost = cost + grid[nx][ny]
                if new_cost < dist[nx][ny]:
                    dist[nx][ny] = new_cost
                    heapq.heappush(pq, (new_cost, nx, ny))

    return -1

# 使用示例
grid = [[0, 1, 1], [1, 1, 1], [1, 0, 0]]
print(shortest_path(grid))  # 输出: 4

详解

  • 使用 Dijkstra 算法来解决最短路径问题。优先队列用于高效选择当前最小代价的节点。时间复杂度为 O((V + E) log V),其中 V 为节点数,E 为边数。

19. 从前序与中序遍历序列构造二叉树(Construct Binary Tree from Preorder and Inorder Traversal)

题目:给定前序遍历和中序遍历的结果,构造出对应的二叉树。

LeetCode 链接Construct Binary Tree from Preorder and Inorder Traversal

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def build_tree(preorder, inorder):
    if not preorder or not inorder:
        return None

    root_val = preorder[0]
    root = TreeNode(root_val)
    root_index = inorder.index(root_val)

    root.left = build_tree(preorder[1:1 + root_index], inorder[:root_index])
    root.right = build_tree(preorder[1 + root_index:], inorder[root_index + 1:])

    return root

# 使用示例
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]
tree = build_tree(preorder, inorder)

详解

  • 利用前序遍历的第一个元素作为根节点,然后根据中序遍历将左右子树划分。递归构建左右子树。时间复杂度为 O(n^2),可以通过哈希表优化为 O(n)。

20. 汉明距离(Hamming Distance)

题目:计算两个整数之间的汉明距离。汉明距离是两个字符串对应位置上不同字符的数量。

LeetCode 链接Hamming Distance

Python 实现

def hamming_distance(x, y):
    return bin(x ^ y).count('1')

# 使用示例
x, y = 1, 4
print(hamming_distance(x, y))  # 输出: 2

详解

  • 通过异或运算找出两个数字的不同位数,然后计算结果中 1 的个数。时间复杂度为 O(1)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖更广泛的算法和数据结构。

21. 寻找两个正序数组的中位数(Median of Two Sorted Arrays)

题目:给定两个大小为 m 和 n 的正序数组 nums1nums2,找出这两个正序数组的中位数。

LeetCode 链接Median of Two Sorted Arrays

Python 实现(O(log(min(m, n))))

def find_median_sorted_arrays(nums1, nums2):
    if len(nums1) > len(nums2):
        nums1, nums2 = nums2, nums1

    x, y = len(nums1), len(nums2)
    low, high = 0, x

    while low <= high:
        partitionX = (low + high) // 2
        partitionY = (x + y + 1) // 2 - partitionX

        maxX = float('-inf') if partitionX == 0 else nums1[partitionX - 1]
        minX = float('inf') if partitionX == x else nums1[partitionX]

        maxY = float('-inf') if partitionY == 0 else nums2[partitionY - 1]
        minY = float('inf') if partitionY == y else nums2[partitionY]

        if maxX <= minY and maxY <= minX:
            if (x + y) % 2 == 0:
                return (max(maxX, maxY) + min(minX, minY)) / 2
            else:
                return max(maxX, maxY)
        elif maxX > minY:
            high = partitionX - 1
        else:
            low = partitionX + 1

    raise ValueError("Input arrays are not sorted correctly")

# 使用示例
nums1 = [1, 3]
nums2 = [2]
print(find_median_sorted_arrays(nums1, nums2))  # 输出: 2.0

详解

  • 利用二分查找法优化时间复杂度到 O(log(min(m, n)))。核心思路是找到两个数组的分区,使得左边的最大值小于等于右边的最小值。

22. 最大矩形(Maximal Rectangle)

题目:给定一个由 '0''1' 组成的二维矩阵,找出包含 '1' 的最大矩形的面积。

LeetCode 链接Maximal Rectangle

Python 实现

def maximal_rectangle(matrix):
    if not matrix:
        return 0

    def largest_rectangle_area(heights):
        stack = []
        max_area = 0
        heights.append(0)
        for i, h in enumerate(heights):
            while stack and h < heights[stack[-1]]:
                height = heights[stack.pop()]
                width = i if not stack else i - stack[-1] - 1
                max_area = max(max_area, height * width)
            stack.append(i)
        heights.pop()
        return max_area

    max_area = 0
    heights = [0] * len(matrix[0])
    for row in matrix:
        for i in range(len(row)):
            heights[i] = heights[i] + 1 if row[i] == '1' else 0
        max_area = max(max_area, largest_rectangle_area(heights))

    return max_area

# 使用示例
matrix = [
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
print(maximal_rectangle(matrix))  # 输出: 6

详解

  • 先将二维矩阵转化为多个柱状图,然后利用柱状图的最大矩形面积来求解。时间复杂度为 O(m * n),其中 m 和 n 分别是矩阵的行数和列数。

23. 单词拆分(Word Break)

题目:给定一个字符串 s 和一个字典 wordDict,判断 s 是否可以被分割为一个或多个字典中的单词。

LeetCode 链接Word Break

Python 实现

def word_break(s, word_dict):
    dp = [False] * (len(s) + 1)
    dp[0] = True
    word_set = set(word_dict)

    for i in range(1, len(s) + 1):
        for j in range(i):
            if dp[j] and s[j:i] in word_set:
                dp[i] = True
                break

    return dp[-1]

# 使用示例
s = "leetcode"
word_dict = ["leet", "code"]
print(word_break(s, word_dict))  # 输出: True

详解

  • 动态规划解决问题,使用 dp 数组标记到达每个位置是否可以被分割。时间复杂度为 O(n^2),空间复杂度为 O(n)。

24. 完全平方数(Perfect Squares)

题目:给定一个正整数 n,找到若干个完全平方数(如 1, 4, 9, 16, ...)的和,使得它们的和为 n

LeetCode 链接Perfect Squares

Python 实现

import math

def num_squares(n):
    dp = [float('inf')] * (n + 1)
    dp[0] = 0

    for i in range(1, n + 1):
        j = 1
        while j * j <= i:
            dp[i] = min(dp[i], dp[i - j * j] + 1)
            j += 1

    return dp[n]

# 使用示例
n = 12
print(num_squares(n))  # 输出: 3

详解

  • 动态规划解决问题,dp[i] 表示和为 i 的最少完全平方数的数量。时间复杂度为 O(n * sqrt(n)),空间复杂度为 O(n)。

25. 反转链表(Reverse Linked List)

题目:反转一个单链表。

LeetCode 链接Reverse Linked List

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverse_list(head):
    prev = None
    curr = head
    while curr:
        next_node = curr.next
        curr.next = prev
        prev = curr
        curr = next_node
    return prev

# 使用示例
# 构造链表 1 -> 2 -> 3 -> 4 -> 5
head = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))

# 反转链表
reversed_head = reverse_list(head)
while reversed_head:
    print(reversed_head.val, end=" -> ")
    reversed_head = reversed_head.next
# 输出: 5 -> 4 -> 3 -> 2 -> 1 ->

详解

  • 通过迭代方式将链表反转。时间复杂度为 O(n),空间复杂度为 O(1)。

26. 删除有序数组中的重复项(Remove Duplicates from Sorted Array)

题目:给定一个排序数组,删除重复项,使得每个元素只出现一次,并返回新数组的长度。

LeetCode 链接Remove Duplicates from Sorted Array

Python 实现

def remove_duplicates(nums):
    if not nums:
        return 0

    unique_index = 0
    for i in range(1, len(nums)):
        if nums[i] != nums[unique_index]:
            unique_index += 1
            nums[unique_index] = nums[i]

    return unique_index + 1

# 使用示例
nums = [1, 1, 2]
length = remove_duplicates(nums)
print(length)  # 输出: 2
print(nums[:length])  # 输出: [1, 2]

详解

  • 由于数组已经排序,使用双指针方法删除重复项。时间复杂度为 O(n),空间复杂度为 O(1)。

27. 有效的括号(Valid Parentheses)

题目:给定一个只包含 '('')''{''}''['']' 的字符串,判断字符串是否有效。有效字符串需满足每个左括号有一个对应的右括号。

LeetCode 链接Valid Parentheses

Python 实现

def is_valid(s):
    stack = []
    mapping = {")": "(", "}": "{", "]": "["}

    for char in s:
        if char in mapping:
            top_element = stack.pop() if stack else '#'
            if mapping[char] != top_element:
                return False
        else:
            stack.append(char)

    return not stack

# 使用示例
s = "()[]{}"
print(is_valid(s))  # 输出: True

详解

  • 使用栈来解决括号匹配问题。时间复杂度为 O(n),空间复杂度为 O(n)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖不同领域和难度层级的题目。

28. 最小路径和(Minimum Path Sum)

题目:给定一个包含非负整数的 m x n 网格,找到一条从左上角到右下角的路径,使得路径上的所有数字之和最小。

LeetCode 链接Minimum Path Sum

Python 实现

def min_path_sum(grid):
    if not grid:
        return 0

    m, n = len(grid), len(grid[0])
    dp = [[0] * n for _ in range(m)]

    dp[0][0] = grid[0][0]

    for i in range(1, m):
        dp[i][0] = dp[i-1][0] + grid[i][0]

    for j in range(1, n):
        dp[0][j] = dp[0][j-1] + grid[0][j]

    for i in range(1, m):
        for j in range(1, n):
            dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]

    return dp[-1][-1]

# 使用示例
grid = [
    [1, 3, 1],
    [1, 5, 1],
    [4, 2, 1]
]
print(min_path_sum(grid))  # 输出: 7

详解

  • 使用动态规划解决问题。dp[i][j] 表示从 (0,0)(i,j) 的最小路径和。时间复杂度为 O(m * n),空间复杂度为 O(m * n)。

29. 组合总和(Combination Sum)

题目:给定一个候选数字的集合 candidates 和一个目标数 target,找出所有可以使数字和为 target 的组合。可以重复使用候选数字。

LeetCode 链接Combination Sum

Python 实现

def combination_sum(candidates, target):
    res = []

    def backtrack(start, path, target):
        if target == 0:
            res.append(path[:])
            return
        for i in range(start, len(candidates)):
            if candidates[i] > target:
                continue
            path.append(candidates[i])
            backtrack(i, path, target - candidates[i])
            path.pop()

    backtrack(0, [], target)
    return res

# 使用示例
candidates = [2, 3, 6, 7]
target = 7
print(combination_sum(candidates, target))  # 输出: [[2, 2, 3], [7]]

详解

  • 使用回溯算法生成所有可能的组合。允许重复使用同一候选数字。时间复杂度为 O(2^n)。

30. 搜索二维矩阵 II(Search a 2D Matrix II)

题目:编写一个高效的算法来搜索 m x n 矩阵中的一个目标值。矩阵的每一行和每一列都是按升序排序的。

LeetCode 链接Search a 2D Matrix II

Python 实现

def search_matrix(matrix, target):
    if not matrix:
        return False

    m, n = len(matrix), len(matrix[0])
    row, col = m - 1, 0

    while row >= 0 and col < n:
        if matrix[row][col] == target:
            return True
        elif matrix[row][col] > target:
            row -= 1
        else:
            col += 1

    return False

# 使用示例
matrix = [
    [1, 4, 7, 11],
    [2, 5, 8, 12],
    [3, 6, 9, 16],
    [10, 13, 14, 17]
]
target = 5
print(search_matrix(matrix, target))  # 输出: True

详解

  • 从矩阵的右上角开始搜索,利用矩阵的排序特性优化搜索过程。时间复杂度为 O(m + n)。

31. 组合(Combinations)

题目:给定两个整数 nk,返回 1n 的所有可能的 k 组合。

LeetCode 链接Combinations

Python 实现

def combine(n, k):
    res = []

    def backtrack(start, path):
        if len(path) == k:
            res.append(path[:])
            return
        for i in range(start, n + 1):
            path.append(i)
            backtrack(i + 1, path)
            path.pop()

    backtrack(1, [])
    return res

# 使用示例
n = 4
k = 2
print(combine(n, k))  # 输出: [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

详解

  • 使用回溯算法生成所有可能的组合。时间复杂度为 O(C(n, k)),其中 C(n, k) 是组合数。

32. 最大子序和(Maximum Subarray)

题目:给定一个整数数组 nums,找到一个具有最大和的连续子数组,并返回其最大和。

LeetCode 链接Maximum Subarray

Python 实现

def max_sub_array(nums):
    max_sum = current_sum = nums[0]

    for num in nums[1:]:
        current_sum = max(num, current_sum + num)
        max_sum = max(max_sum, current_sum)

    return max_sum

# 使用示例
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
print(max_sub_array(nums))  # 输出: 6

详解

  • 使用 Kadane 算法解决问题,时间复杂度为 O(n),空间复杂度为 O(1)。

33. 搜索旋转排序数组(Search in Rotated Sorted Array)

题目:给定一个旋转排序数组和一个目标值 target,请找出目标值是否在数组中,并返回其索引。如果数组中不存在目标值,返回 -1。

LeetCode 链接Search in Rotated Sorted Array

Python 实现

def search(nums, target):
    left, right = 0, len(nums) - 1

    while left <= right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        if nums[left] <= nums[mid]:
            if nums[left] <= target < nums[mid]:
                right = mid - 1
            else:
                left = mid + 1
        else:
            if nums[mid] < target <= nums[right]:
                left = mid + 1
            else:
                right = mid - 1

    return -1

# 使用示例
nums = [4, 5, 6, 7, 0, 1, 2]
target = 0
print(search(nums, target))  # 输出: 4

详解

  • 使用修改版的二分查找算法来处理旋转排序数组。时间复杂度为 O(log n)。

34. 旋转图像(Rotate Image)

题目:给定一个 n x n 的二维矩阵 matrix,将其顺时针旋转 90 度。

LeetCode 链接Rotate Image

Python 实现

def rotate(matrix):
    n = len(matrix)

    # 转置矩阵
    for i in range(n):
        for j in range(i, n):
            matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

    # 反转每一行
    for i in range(n):
        matrix[i].reverse()

# 使用示例
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]
rotate(matrix)
print(matrix)  # 输出: [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

详解

  • 先进行矩阵转置,再反转每一行。时间复杂度为 O(n^2),空间复杂度为 O(1)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖不同的算法和数据结构。

35. 字符串的排列(Permutation in String)

题目:给定两个字符串 s1s2,判断 s2 是否包含 s1 的排列。即:s2 是否包含 s1 的某个排列的子串。

LeetCode 链接Permutation in String

Python 实现

from collections import Counter

def check_inclusion(s1, s2):
    s1_count = Counter(s1)
    s2_count = Counter()
    len_s1 = len(s1)

    for i in range(len(s2)):
        s2_count[s2[i]] += 1
        if i >= len_s1:
            if s2_count[s2[i - len_s1]] == 1:
                del s2_count[s2[i - len_s1]]
            else:
                s2_count[s2[i - len_s1]] -= 1

        if s2_count == s1_count:
            return True

    return False

# 使用示例
s1 = "ab"
s2 = "eidbaooo"
print(check_inclusion(s1, s2))  # 输出: True

详解

  • 使用滑动窗口和计数器来检查 s2 是否包含 s1 的排列。时间复杂度为 O(n),空间复杂度为 O(1)。

36. 最大正方形(Maximal Square)

题目:给定一个只包含 '0''1' 的二维矩阵,找出只包含 '1' 的最大正方形,并返回其面积。

LeetCode 链接Maximal Square

Python 实现

def maximal_square(matrix):
    if not matrix:
        return 0

    m, n = len(matrix), len(matrix[0])
    dp = [[0] * n for _ in range(m)]
    max_side = 0

    for i in range(m):
        for j in range(n):
            if matrix[i][j] == '1':
                if i == 0 or j == 0:
                    dp[i][j] = 1
                else:
                    dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
                max_side = max(max_side, dp[i][j])

    return max_side * max_side

# 使用示例
matrix = [
    ["1","0","1","0","0"],
    ["1","0","1","1","1"],
    ["1","1","1","1","1"],
    ["1","0","0","1","0"]
]
print(maximal_square(matrix))  # 输出: 4

详解

  • 使用动态规划来计算每个点形成的最大正方形的边长。时间复杂度为 O(m * n),空间复杂度为 O(m * n)。

37. 编辑距离(Edit Distance)

题目:给定两个字符串 word1word2,计算将 word1 转换为 word2 所需的最小操作数。操作包括插入一个字符、删除一个字符和替换一个字符。

LeetCode 链接Edit Distance

Python 实现

def min_distance(word1, word2):
    m, n = len(word1), len(word2)
    dp = [[0] * (n + 1) for _ in range(m + 1)]

    for i in range(m + 1):
        for j in range(n + 1):
            if i == 0:
                dp[i][j] = j
            elif j == 0:
                dp[i][j] = i
            elif word1[i - 1] == word2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = 1 + min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])

    return dp[m][n]

# 使用示例
word1 = "horse"
word2 = "ros"
print(min_distance(word1, word2))  # 输出: 3

详解

  • 使用动态规划来计算最小编辑距离。时间复杂度为 O(m * n),空间复杂度为 O(m * n)。

38. 爬楼梯(Climbing Stairs)

题目:假设你正在爬楼梯。楼梯有 n 阶,每次你可以爬 1 阶或 2 阶。计算到达第 n 阶有多少种不同的方法。

LeetCode 链接Climbing Stairs

Python 实现

def climb_stairs(n):
    if n <= 1:
        return 1

    a, b = 1, 1
    for _ in range(2, n + 1):
        a, b = b, a + b

    return b

# 使用示例
n = 5
print(climb_stairs(n))  # 输出: 8

详解

  • 使用动态规划解决问题。时间复杂度为 O(n),空间复杂度为 O(1)。

39. 合并区间(Merge Intervals)

题目:给定一个区间的集合,合并所有重叠的区间。

LeetCode 链接Merge Intervals

Python 实现

def merge(intervals):
    if not intervals:
        return []

    intervals.sort(key=lambda x: x[0])
    merged = [intervals[0]]

    for current in intervals[1:]:
        last = merged[-1]
        if current[0] <= last[1]:
            last[1] = max(last[1], current[1])
        else:
            merged.append(current)

    return merged

# 使用示例
intervals = [[1, 3], [2, 6], [8, 10], [15, 18]]
print(merge(intervals))  # 输出: [[1, 6], [8, 10], [15, 18]]

详解

  • 先对区间进行排序,然后合并重叠的区间。时间复杂度为 O(n log n),空间复杂度为 O(n)。

40. 最小窗口子串(Minimum Window Substring)

题目:给定一个字符串 s 和一个字符串 t,找出 s 中包含 t 所有字符的最小窗口子串。

LeetCode 链接Minimum Window Substring

Python 实现

from collections import Counter

def min_window(s, t):
    if not s or not t:
        return ""

    t_count = Counter(t)
    s_count = Counter()

    left, right = 0, 0
    min_len = float('inf')
    min_window = ""

    while right < len(s):
        s_count[s[right]] += 1
        while all(s_count[c] >= t_count[c] for c in t_count):
            if right - left + 1 < min_len:
                min_len = right - left + 1
                min_window = s[left:right + 1]
            s_count[s[left]] -= 1
            left += 1
        right += 1

    return min_window

# 使用示例
s = "ADOBECODEBANC"
t = "ABC"
print(min_window(s, t))  # 输出: "BANC"

详解

  • 使用滑动窗口和计数器来找出包含所有目标字符的最小窗口子串。时间复杂度为 O(n),空间复杂度为 O(n)。

41. 最长公共前缀(Longest Common Prefix)

题目:编写一个函数来查找字符串数组中的最长公共前缀。如果没有公共前缀,返回空字符串 ""

LeetCode 链接Longest Common Prefix

Python 实现

def longest_common_prefix(strs):
    if not strs:
        return ""

    min_len = min(len(s) for s in strs)

    for i in range(min_len):
        char = strs[0][i]
        for s in strs[1:]:
            if s[i] != char:
                return strs[0][:i]

    return strs[0][:min_len]

# 使用示例
strs = ["flower", "flow", "flight"]
print(longest_common_prefix(strs))  # 输出: "fl"

详解

  • 比较所有字符串的字符来找出最长公共前缀。时间复杂度为 O(S),其中 S 是所有字符串的字符总数。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖不同的算法和数据结构。

42. 盛最多水的容器(Container With Most Water)

题目:给定一个整数数组 height,其中 height[i] 是第 i 条垂直线的高度。找到两条线,使得它们和 x 轴之间形成的容器可以容纳最多的水,并返回这个最大值。

LeetCode 链接Container With Most Water

Python 实现

def max_area(height):
    left, right = 0, len(height) - 1
    max_area = 0

    while left < right:
        width = right - left
        min_height = min(height[left], height[right])
        max_area = max(max_area, width * min_height)

        if height[left] < height[right]:
            left += 1
        else:
            right -= 1

    return max_area

# 使用示例
height = [1,8,6,2,5,4,8,3,7]
print(max_area(height))  # 输出: 49

详解

  • 使用双指针法来优化搜索。时间复杂度为 O(n),空间复杂度为 O(1)。

43. 字符串乘法(Multiply Strings)

题目:给定两个非负整数 num1num2 表示为字符串,返回它们的乘积,结果也应该是字符串形式。

LeetCode 链接Multiply Strings

Python 实现

def multiply(num1, num2):
    if num1 == "0" or num2 == "0":
        return "0"

    m, n = len(num1), len(num2)
    result = [0] * (m + n)

    for i in range(m-1, -1, -1):
        for j in range(n-1, -1, -1):
            mul = (ord(num1[i]) - ord('0')) * (ord(num2[j]) - ord('0'))
            p1, p2 = i + j, i + j + 1
            summ = mul + result[p2]

            result[p2] = summ % 10
            result[p1] += summ // 10

    result_str = ''.join(map(str, result))
    return result_str.lstrip('0')

# 使用示例
num1 = "123"
num2 = "456"
print(multiply(num1, num2))  # 输出: "56088"

详解

  • 使用模拟乘法算法来计算结果。时间复杂度为 O(m * n),空间复杂度为 O(m + n)。

44. 通配符匹配(Wildcard Matching)

题目:给定两个字符串 sp,其中 p 可能包含通配符 *?* 表示零个或多个字符,? 表示一个字符。判断字符串 s 是否与 p 匹配。

LeetCode 链接Wildcard Matching

Python 实现

def is_match(s, p):
    m, n = len(s), len(p)
    dp = [[False] * (n + 1) for _ in range(m + 1)]
    dp[0][0] = True

    for j in range(1, n + 1):
        dp[0][j] = dp[0][j - 1] and p[j - 1] == '*'

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if p[j - 1] == '*':
                dp[i][j] = dp[i][j - 1] or dp[i - 1][j]
            elif p[j - 1] == '?' or p[j - 1] == s[i - 1]:
                dp[i][j] = dp[i - 1][j - 1]

    return dp[m][n]

# 使用示例
s = "aa"
p = "a*"
print(is_match(s, p))  # 输出: True

详解

  • 使用动态规划来解决通配符匹配问题。时间复杂度为 O(m * n),空间复杂度为 O(m * n)。

45. 跳跃游戏 II(Jump Game II)

题目:给定一个非负整数数组 nums,你最初位于数组的第一个下标。数组中的每个元素代表你在该位置可以跳跃的最大长度。求跳到最后一个下标的最小跳跃次数。

LeetCode 链接Jump Game II

Python 实现

def jump(nums):
    jumps = 0
    current_end = 0
    farthest = 0

    for i in range(len(nums) - 1):
        farthest = max(farthest, i + nums[i])
        if i == current_end:
            jumps += 1
            current_end = farthest

    return jumps

# 使用示例
nums = [2,3,1,1,2,4,2,0,1,1]
print(jump(nums))  # 输出: 4

详解

  • 使用贪心算法来计算最小跳跃次数。时间复杂度为 O(n),空间复杂度为 O(1)。

46. 全排列(Permutations)

题目:给定一个没有重复数字的整数数组 nums,返回其所有可能的全排列。

LeetCode 链接Permutations

Python 实现

def permute(nums):
    def backtrack(path):
        if len(path) == len(nums):
            res.append(path[:])
            return
        for num in nums:
            if num in path:
                continue
            path.append(num)
            backtrack(path)
            path.pop()

    res = []
    backtrack([])
    return res

# 使用示例
nums = [1, 2, 3]
print(permute(nums))  # 输出: [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

详解

  • 使用回溯算法生成所有可能的排列。时间复杂度为 O(n!),空间复杂度为 O(n)。

47. 全排列 II(Permutations II)

题目:给定一个可能包含重复数字的整数数组 nums,返回其所有不同的全排列。

LeetCode 链接Permutations II

Python 实现

def permute_unique(nums):
    def backtrack(path):
        if len(path) == len(nums):
            res.append(path[:])
            return
        for i in range(len(nums)):
            if visited[i] or (i > 0 and nums[i] == nums[i - 1] and not visited[i - 1]):
                continue
            visited[i] = True
            path.append(nums[i])
            backtrack(path)
            path.pop()
            visited[i] = False

    nums.sort()
    visited = [False] * len(nums)
    res = []
    backtrack([])
    return res

# 使用示例
nums = [1, 1, 2]
print(permute_unique(nums))  # 输出: [[1, 1, 2], [1, 2, 1], [2, 1, 1]]

详解

  • 使用回溯算法生成所有不同的排列。时间复杂度为 O(n!),空间复杂度为 O(n)。

48. 旋转图像(Rotate Image)

题目:给定一个 n x n 的二维矩阵 matrix,将其顺时针旋转 90 度。

LeetCode 链接Rotate Image

Python 实现

def rotate(matrix):
    n = len(matrix)

    # 转置矩阵
    for i in range(n):
        for j in range(i, n):
            matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

    # 反转每一行
    for i in range(n):
        matrix[i].reverse()

# 使用示例
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]
rotate(matrix)
print(matrix)  # 输出: [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

详解

  • 首先进行矩阵转置,然后反转每一行。时间复杂度为 O(n^2),空间复杂度为 O(1)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖不同的算法和数据结构。

49. 字母异位词分组(Group Anagrams)

题目:给定一个字符串数组,将所有字母异位词分到同一组。字母异位词是指两个字符串包含相同的字符,且每个字符出现的次数也相同。

LeetCode 链接Group Anagrams

Python 实现

from collections import defaultdict

def group_anagrams(strs):
    anagram_map = defaultdict(list)

    for s in strs:
        sorted_str = ''.join(sorted(s))
        anagram_map[sorted_str].append(s)

    return list(anagram_map.values())

# 使用示例
strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
print(group_anagrams(strs))  # 输出: [['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]

详解

  • 使用哈希表来存储按字母排序后的字符串及其对应的原字符串。时间复杂度为 O(n * k log k),空间复杂度为 O(n * k),其中 n 为字符串数,k 为字符串的最大长度。

50. Pow(x, n)(实现 pow(x, n))

题目:实现 pow(x, n),即计算 xn 次幂。

LeetCode 链接Pow(x, n)

Python 实现

def my_pow(x, n):
    if n == 0:
        return 1
    elif n < 0:
        x = 1 / x
        n = -n

    half = my_pow(x, n // 2)
    if n % 2 == 0:
        return half * half
    else:
        return half * half * x

# 使用示例
x = 2.00000
n = 10
print(my_pow(x, n))  # 输出: 1024.00000

详解

  • 使用递归法来计算幂,时间复杂度为 O(log n),空间复杂度为 O(log n)。

51. N 皇后(N-Queens)

题目:n 皇后问题是一个经典的计算机科学问题,要求在一个 n x n 的棋盘上放置 n 个皇后,使得它们彼此之间不能相互攻击。实现一个算法,返回所有有效的 n 皇后问题的解决方案。

LeetCode 链接N-Queens

Python 实现

def solve_n_queens(n):
    def is_not_under_attack(row, col):
        for prev_row in range(row):
            if board[prev_row] == col or \
               board[prev_row] - prev_row == col - row or \
               board[prev_row] + prev_row == col + row:
                return False
        return True

    def backtrack(row):
        if row == n:
            result.append(["".join(['Q' if col == board[i] else '.' for col in range(n)]) for i in range(n)])
            return
        for col in range(n):
            if is_not_under_attack(row, col):
                board[row] = col
                backtrack(row + 1)
                board[row] = -1

    result = []
    board = [-1] * n
    backtrack(0)
    return result

# 使用示例
n = 4
print(solve_n_queens(n))  # 输出: [['.Q..', '...Q', 'Q...', '..Q.'], ['..Q.', 'Q...', '...Q', '.Q..']]

详解

  • 使用回溯算法来解决 n 皇后问题。时间复杂度为 O(n!),空间复杂度为 O(n)。

52. N 皇后 II(N-Queens II)

题目:与 N 皇后类似,但只需要返回有效的解决方案的数量,而不是具体的布局。

LeetCode 链接N-Queens II

Python 实现

def total_n_queens(n):
    def is_not_under_attack(row, col):
        for prev_row in range(row):
            if board[prev_row] == col or \
               board[prev_row] - prev_row == col - row or \
               board[prev_row] + prev_row == col + row:
                return False
        return True

    def backtrack(row):
        if row == n:
            nonlocal count
            count += 1
            return
        for col in range(n):
            if is_not_under_attack(row, col):
                board[row] = col
                backtrack(row + 1)
                board[row] = -1

    count = 0
    board = [-1] * n
    backtrack(0)
    return count

# 使用示例
n = 4
print(total_n_queens(n))  # 输出: 2

详解

  • 使用回溯算法计算有效解决方案的数量。时间复杂度为 O(n!),空间复杂度为 O(n)。

53. 最大子数组和(Maximum Subarray)

题目:给定一个整数数组 nums,找出具有最大和的连续子数组,并返回其和。

LeetCode 链接Maximum Subarray

Python 实现

def max_sub_array(nums):
    max_sum = nums[0]
    current_sum = nums[0]

    for num in nums[1:]:
        current_sum = max(num, current_sum + num)
        max_sum = max(max_sum, current_sum)

    return max_sum

# 使用示例
nums = [-2,1,-3,4,-1,2,1,-5,4]
print(max_sub_array(nums))  # 输出: 6

详解

  • 使用动态规划(Kadane 算法)计算最大子数组和。时间复杂度为 O(n),空间复杂度为 O(1)。

54. 螺旋矩阵(Spiral Matrix)

题目:给定一个 m x n 的矩阵 matrix,按照螺旋顺序返回矩阵中的所有元素。

LeetCode 链接Spiral Matrix

Python 实现

def spiral_order(matrix):
    if not matrix:
        return []

    result = []
    top, bottom, left, right = 0, len(matrix), 0, len(matrix[0])

    while top < bottom and left < right:
        for col in range(left, right):
            result.append(matrix[top][col])
        top += 1

        for row in range(top, bottom):
            result.append(matrix[row][right - 1])
        right -= 1

        if not (top < bottom and left < right):
            break

        for col in range(right - 1, left - 1, -1):
            result.append(matrix[bottom - 1][col])
        bottom -= 1

        for row in range(bottom - 1, top - 1, -1):
            result.append(matrix[row][left])
        left += 1

    return result

# 使用示例
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]
print(spiral_order(matrix))  # 输出: [1, 2, 3, 6, 9, 8, 7, 4, 5]

详解

  • 使用边界变量来控制螺旋顺序的循环。时间复杂度为 O(m * n),空间复杂度为 O(1)。

55. 跳跃游戏(Jump Game)

题目:给定一个非负整数数组 nums,你最初位于数组的第一个下标。每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达数组的最后一个下标。

LeetCode 链接Jump Game

Python 实现

def can_jump(nums):
    max_reachable = 0
    for i, jump in enumerate(nums):
        if i > max_reachable:
            return False
        max_reachable = max(max_reachable, i + jump)
    return True

# 使用示例
nums = [2, 3, 1, 1, 4]
print(can_jump(nums))  # 输出: True

详解

  • 使用贪心算法来判断是否可以到达最后一个下标。时间复杂度为 O(n),空间复杂度为 O(1)。

56. 合并区间(Merge Intervals)

题目:给定一个区间的集合,合并所有重叠的区间。

LeetCode 链接Merge Intervals

Python 实现

def merge(intervals):
    if not intervals:
        return []

    intervals.sort(key=lambda x: x[0])
    merged = [intervals[0]]

    for current in intervals[1:]:
        last_merged = merged[-1]
        if current[0] <= last_merged[1]:
            last_merged[1] = max(last_merged[1], current[1])
        else:
            merged.append(current)

    return merged

# 使用示例
intervals = [[1,3],[2,6],[8,10],[15,18]]
print(merge(intervals))  # 输出: [[1,6],[8,10],[15,18]]

详解

  • 先对区间进行排序,然后合并重叠的区间。时间复杂度为 O(n log n),空间复杂度为 O(n)。

57. 插入区间(Insert Interval)

题目:给定一个不重叠的区间列表 intervals 和一个新的区间 new_interval,将新的区间插入到列表中,并合并所有重叠的区间。

LeetCode 链接Insert Interval

Python 实现

def insert(intervals, new_interval):
    merged = []
    i = 0
    n = len(intervals)

    # 添加所有在 new_interval 左边的区间
    while i < n and intervals[i][1] < new_interval[0]:
        merged.append(intervals[i])
        i += 1

    # 合并所有重叠的区间
    while i < n and intervals[i][0] <= new_interval[1]:
        new_interval[0] = min(new_interval[0], intervals[i][0])
        new_interval[1] = max(new_interval[1], intervals[i][1])
        i += 1

    merged.append(new_interval)

    # 添加所有在 new_interval 右边的区间
    while i < n:
        merged.append(intervals[i])
        i += 1

    return merged

# 使用示例
intervals = [[1,3],[6,9]]
new_interval = [2,5]
print(insert(intervals, new_interval))  # 输出: [[1,5],[6,9]]

详解

  • 将新的区间插入到正确的位置,并合并所有重叠的区间。时间复杂度为 O(n),空间复杂度为 O(n)。

58. 最后一个单词的长度(Length of Last Word)

题目:给定一个字符串 s,其中仅包含字母和空格,返回字符串最后一个单词的长度。单词是由非空格字符组成的。

LeetCode 链接Length of Last Word

Python 实现

def length_of_last_word(s):
    words = s.split()
    if not words:
        return 0
    return len(words[-1])

# 使用示例
s = "Hello World"
print(length_of_last_word(s))  # 输出: 5

详解

  • 通过分割字符串并返回最后一个单词的长度。时间复杂度为 O(n),空间复杂度为 O(n)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖不同的算法和数据结构。

59. 螺旋矩阵 II(Spiral Matrix II)

题目:给定一个正整数 n,生成一个 n x n 的矩阵,其中矩阵中的元素按螺旋顺序填充。

LeetCode 链接Spiral Matrix II

Python 实现

def generate_matrix(n):
    matrix = [[0] * n for _ in range(n)]
    num = 1
    top, bottom, left, right = 0, n, 0, n

    while top < bottom and left < right:
        for col in range(left, right):
            matrix[top][col] = num
            num += 1
        top += 1

        for row in range(top, bottom):
            matrix[row][right - 1] = num
            num += 1
        right -= 1

        if not (top < bottom and left < right):
            break

        for col in range(right - 1, left - 1, -1):
            matrix[bottom - 1][col] = num
            num += 1
        bottom -= 1

        for row in range(bottom - 1, top - 1, -1):
            matrix[row][left] = num
            num += 1
        left += 1

    return matrix

# 使用示例
n = 3
print(generate_matrix(n))
# 输出: [[1, 2, 3], [8, 9, 4], [7, 6, 5]]

详解

  • 使用边界变量控制螺旋顺序的填充。时间复杂度为 O(n^2),空间复杂度为 O(1)。

60. 排列序列(Permutation Sequence)

题目:给定两个整数 nk,返回第 k 个排列序列。

LeetCode 链接Permutation Sequence

Python 实现

from math import factorial

def get_permutation(n, k):
    nums = list(range(1, n + 1))
    k -= 1
    permutation = []

    for i in range(n):
        fact = factorial(n - 1 - i)
        index, k = divmod(k, fact)
        permutation.append(nums.pop(index))

    return ''.join(map(str, permutation))

# 使用示例
n = 3
k = 3
print(get_permutation(n, k))  # 输出: "213"

详解

  • 使用阶乘来计算排列位置。时间复杂度为 O(n^2),空间复杂度为 O(n)。

61. 旋转链表(Rotate List)

题目:给定一个链表,将链表的每个节点向右移动 k 个位置。

LeetCode 链接Rotate List

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def rotate_right(head, k):
    if not head or k == 0:
        return head

    # 计算链表长度
    length = 1
    old_tail = head
    while old_tail.next:
        old_tail = old_tail.next
        length += 1

    # 计算实际旋转次数
    k %= length
    if k == 0:
        return head

    # 找到新的尾部和头部
    new_tail = head
    for _ in range(length - k - 1):
        new_tail = new_tail.next
    new_head = new_tail.next
    new_tail.next = None
    old_tail.next = head

    return new_head

# 使用示例
head = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5))))))
k = 2
result = rotate_right(head, k)
while result:
    print(result.val, end=" -> ")
    result = result.next
# 输出: 4 -> 5 -> 1 -> 2 -> 3

详解

  • 先计算链表长度,然后找到旋转后的新头和尾。时间复杂度为 O(n),空间复杂度为 O(1)。

62. 不同路径(Unique Paths)

题目:一个机器人位于一个 m x n 的网格的左上角。机器人只能向右或向下移动。计算机器人到达网格右下角的不同路径数。

LeetCode 链接Unique Paths

Python 实现

def unique_paths(m, n):
    dp = [[1] * n for _ in range(m)]

    for i in range(1, m):
        for j in range(1, n):
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1]

    return dp[-1][-1]

# 使用示例
m = 3
n = 7
print(unique_paths(m, n))  # 输出: 28

详解

  • 使用动态规划计算不同路径数。时间复杂度为 O(m * n),空间复杂度为 O(m * n)。

63. 不同路径 II(Unique Paths II)

题目:一个机器人位于一个 m x n 的网格的左上角,网格中有一些障碍物。计算机器人到达网格右下角的不同路径数。

LeetCode 链接Unique Paths II

Python 实现

def unique_paths_with_obstacles(grid):
    if not grid or grid[0][0] == 1:
        return 0

    m, n = len(grid), len(grid[0])
    dp = [[0] * n for _ in range(m)]
    dp[0][0] = 1

    for i in range(m):
        for j in range(n):
            if grid[i][j] == 1:
                dp[i][j] = 0
            else:
                if i > 0:
                    dp[i][j] += dp[i - 1][j]
                if j > 0:
                    dp[i][j] += dp[i][j - 1]

    return dp[-1][-1]

# 使用示例
grid = [
    [0,0,0],
    [0,1,0],
    [0,0,0]
]
print(unique_paths_with_obstacles(grid))  # 输出: 2

详解

  • 使用动态规划处理障碍物的情况。时间复杂度为 O(m * n),空间复杂度为 O(m * n)。

64. 最小路径和(Minimum Path Sum)

题目:给定一个 m x n 的网格,初始化时每个格子都有一个非负整数。计算从左上角到右下角的路径和最小值,路径只能向右或向下。

LeetCode 链接Minimum Path Sum

Python 实现

def min_path_sum(grid):
    m, n = len(grid), len(grid[0])

    for i in range(1, m):
        grid[i][0] += grid[i - 1][0]

    for j in range(1, n):
        grid[0][j] += grid[0][j - 1]

    for i in range(1, m):
        for j in range(1, n):
            grid[i][j] += min(grid[i - 1][j], grid[i][j - 1])

    return grid[-1][-1]

# 使用示例
grid = [
    [1,3,1],
    [1,5,1],
    [4,2,1]
]
print(min_path_sum(grid))  # 输出: 7

详解

  • 使用动态规划计算最小路径和。时间复杂度为 O(m * n),空间复杂度为 O(1)。

65. 有效数字(Valid Number)

题目:验证给定的字符串是否是一个有效的数字。有效的数字可以是整数、浮点数(正数或负数)、科学计数法表示的数字。

LeetCode 链接Valid Number

Python 实现

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

# 使用示例
s = "0.1"
print(is_number(s))  # 输出: True

详解

  • 使用 Python 内置的 float 函数来验证字符串是否可以被转换为有效的数字。时间复杂度为 O(1),空间复杂度为 O(1)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖不同的算法和数据结构。

66. 加一(Plus One)

题目:给定一个由非负整数组成的整数数组 digits,表示一个大于 0 的整数,返回该整数加一后的数组表示。

LeetCode 链接Plus One

Python 实现

def plus_one(digits):
    for i in range(len(digits) - 1, -1, -1):
        if digits[i] < 9:
            digits[i] += 1
            return digits
        digits[i] = 0

    return [1] + digits

# 使用示例
digits = [1, 2, 3]
print(plus_one(digits))  # 输出: [1, 2, 4]

详解

  • 从右到左遍历数组,处理进位。时间复杂度为 O(n),空间复杂度为 O(1)。

67. 二进制求和(Add Binary)

题目:给定两个二进制字符串,返回它们的和(也即它们的二进制字符串形式)。

LeetCode 链接Add Binary

Python 实现

def add_binary(a, b):
    return bin(int(a, 2) + int(b, 2))[2:]

# 使用示例
a = "1010"
b = "1011"
print(add_binary(a, b))  # 输出: "10101"

详解

  • 将二进制字符串转换为整数,进行加法运算,然后转换回二进制字符串。时间复杂度为 O(max(m, n)),空间复杂度为 O(1),其中 m 和 n 为字符串的长度。

68. 文本左右对齐(Text Justification)

题目:给定一个单词数组 words 和一个最大宽度 max_width,将单词排成一行,并使每行的文本尽可能对齐。

LeetCode 链接Text Justification

Python 实现

def full_justify(words, max_width):
    def add_spaces(words, max_width, is_last_line):
        if len(words) == 1:
            return words[0] + ' ' * (max_width - len(words[0]))

        total_spaces = max_width - sum(len(word) for word in words)
        spaces_between_words = total_spaces // (len(words) - 1)
        extra_spaces = total_spaces % (len(words) - 1)

        result = ''
        for i in range(len(words) - 1):
            result += words[i] + ' ' * (spaces_between_words + (1 if i < extra_spaces else 0))
        result += words[-1]
        return result

    result, current_line, num_of_letters = [], [], 0

    for word in words:
        if num_of_letters + len(word) + len(current_line) > max_width:
            result.append(add_spaces(current_line, max_width, False))
            current_line, num_of_letters = [], 0
        current_line.append(word)
        num_of_letters += len(word)

    result.append(' '.join(current_line).ljust(max_width))

    return result

# 使用示例
words = ["This", "is", "an", "example", "of", "text", "justification."]
max_width = 16
print(full_justify(words, max_width))
# 输出:
# ["This    is    an", 
#  "example  of text", 
#  "justification.  "]

详解

  • 使用两步处理:计算每行的空间分配,然后将结果添加到输出列表。时间复杂度为 O(n),空间复杂度为 O(n)。

69. Sqrt(x)(x 的平方根)

题目:实现 sqrt(x) 函数,计算并返回 x 的平方根。

LeetCode 链接Sqrt(x)

Python 实现

def my_sqrt(x):
    if x < 2:
        return x

    left, right = 2, x // 2
    while left <= right:
        mid = (left + right) // 2
        num = mid * mid
        if num == x:
            return mid
        elif num < x:
            left = mid + 1
        else:
            right = mid - 1

    return right

# 使用示例
x = 8
print(my_sqrt(x))  # 输出: 2

详解

  • 使用二分查找算法来找到平方根的整数部分。时间复杂度为 O(log x),空间复杂度为 O(1)。

70. 爬楼梯(Climbing Stairs)

题目:一只青蛙一次可以跳 1 步或 2 步,计算爬到楼梯顶部的不同方式的数量。

LeetCode 链接Climbing Stairs

Python 实现

def climb_stairs(n):
    if n <= 1:
        return 1

    prev, curr = 1, 1
    for _ in range(2, n + 1):
        prev, curr = curr, prev + curr

    return curr

# 使用示例
n = 5
print(climb_stairs(n))  # 输出: 8

详解

  • 使用动态规划计算爬楼梯的不同方式。时间复杂度为 O(n),空间复杂度为 O(1)。

71. 简化路径(Simplify Path)

题目:给定一个绝对路径的文件路径,简化路径,使其符合 Unix 文件系统的标准格式。

LeetCode 链接Simplify Path

Python 实现

def simplify_path(path):
    stack = []
    for part in path.split('/'):
        if part == '..':
            if stack:
                stack.pop()
        elif part and part != '.':
            stack.append(part)

    return '/' + '/'.join(stack)

# 使用示例
path = "/a/./b/../../c/"
print(simplify_path(path))  # 输出: "/c"

详解

  • 使用栈来处理路径的简化。时间复杂度为 O(n),空间复杂度为 O(n)。

72. 编辑距离(Edit Distance)

题目:给定两个单词 word1word2,计算将 word1 转换为 word2 所需的最小操作次数。操作包括插入、删除和替换。

LeetCode 链接Edit Distance

Python 实现

def min_distance(word1, word2):
    m, n = len(word1), len(word2)
    dp = [[0] * (n + 1) for _ in range(m + 1)]

    for i in range(m + 1):
        for j in range(n + 1):
            if i == 0:
                dp[i][j] = j
            elif j == 0:
                dp[i][j] = i
            elif word1[i - 1] == word2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]
            else:
                dp[i][j] = 1 + min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])

    return dp[m][n]

# 使用示例
word1 = "intention"
word2 = "execution"
print(min_distance(word1, word2))  # 输出: 5

详解

  • 使用动态规划计算编辑距离。时间复杂度为 O(m * n),空间复杂度为 O(m * n),其中 m 和 n 为两个单词的长度。

73. 矩阵置零(Set Matrix Zeroes)

题目:给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列都置为 0。

LeetCode 链接Set Matrix Zeroes

Python 实现

def set_zeroes(matrix):
    rows, cols = len(matrix), len(matrix[0])
    row_zero = any(matrix[0][j] == 0 for j in range(cols))
    col_zero = any(matrix[i][0] == 0 for i in range(rows))

    for i in range(1, rows):
        for j in range(1, cols):
            if matrix[i][j] == 0:
                matrix[i][0] = matrix[0][j] = 0

    for i in range(1, rows):
        for j in range(1, cols):
            if matrix[i][0] == 0 or matrix[0][j] == 0:
                matrix[i][j] = 0

    if row_zero:
        for j in range(cols):
            matrix[0][j] = 0

    if col_zero:
        for i in range(rows):
            matrix[i][0] = 0

# 使用示例
matrix = [
    [1, 2, 3],
    [4, 0, 6],
    [7, 8, 9]
]
set_zeroes(matrix)
for row in matrix:
    print(row)
# 输出:
# [1, 0, 0]
# [0, 0, 0]
# [7, 0, 9]

详解

  • 使用两个额外的变量来跟踪第一行和第一列是否需要置零。时间复杂度为 O(m * n),空间复杂度为 O(1)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖不同的算法和数据结构。

74. 搜索二维矩阵(Search a 2D Matrix)

题目:编写一个高效的算法来搜索一个二维矩阵中的目标值。矩阵中的每一行和每一列都已按升序排序。

LeetCode 链接Search a 2D Matrix

Python 实现

def search_matrix(matrix, target):
    if not matrix:
        return False

    m, n = len(matrix), len(matrix[0])
    left, right = 0, m * n - 1

    while left <= right:
        mid = (left + right) // 2
        mid_val = matrix[mid // n][mid % n]
        if mid_val == target:
            return True
        elif mid_val < target:
            left = mid + 1
        else:
            right = mid - 1

    return False

# 使用示例
matrix = [
    [1, 4, 7, 11],
    [2, 5, 8, 12],
    [3, 6, 9, 16],
    [10, 13, 14, 17]
]
target = 5
print(search_matrix(matrix, target))  # 输出: True

详解

  • 使用二分查找算法在二维矩阵中查找目标值。时间复杂度为 O(log(m * n)),空间复杂度为 O(1)。

75. 颜色分类(Sort Colors)

题目:给定一个包含红色、白色和蓝色(即 0、1 和 2)的数组,将它们按颜色排序。你需要在原地进行排序,并且算法的时间复杂度必须为 O(n)。

LeetCode 链接Sort Colors

Python 实现

def sort_colors(nums):
    low, mid, high = 0, 0, len(nums) - 1

    while mid <= high:
        if nums[mid] == 0:
            nums[low], nums[mid] = nums[mid], nums[low]
            low += 1
            mid += 1
        elif nums[mid] == 1:
            mid += 1
        else:
            nums[mid], nums[high] = nums[high], nums[mid]
            high -= 1

# 使用示例
nums = [2, 0, 2, 1, 1, 0]
sort_colors(nums)
print(nums)  # 输出: [0, 0, 1, 1, 2, 2]

详解

  • 使用荷兰国旗问题的三指针算法进行排序。时间复杂度为 O(n),空间复杂度为 O(1)。

76. 最小窗口子串(Minimum Window Substring)

题目:给定两个字符串 st,找到 s 中包含 t 的所有字符的最小子串。

LeetCode 链接Minimum Window Substring

Python 实现

from collections import Counter

def min_window(s, t):
    if not s or not t:
        return ""

    t_count = Counter(t)
    s_count = Counter()
    required = len(t_count)
    left, right = 0, 0
    min_len = float("inf")
    min_window = ""

    while right < len(s):
        char = s[right]
        s_count[char] += 1
        if char in t_count and s_count[char] == t_count[char]:
            required -= 1

        while required == 0:
            if right - left + 1 < min_len:
                min_len = right - left + 1
                min_window = s[left:right + 1]

            s_count[s[left]] -= 1
            if s[left] in t_count and s_count[s[left]] < t_count[s[left]]:
                required += 1
            left += 1

        right += 1

    return min_window

# 使用示例
s = "ADOBECODEBANC"
t = "ABC"
print(min_window(s, t))  # 输出: "BANC"

详解

  • 使用滑动窗口算法来找到最小窗口子串。时间复杂度为 O(n),空间复杂度为 O(n)。

77. 组合(Combinations)

题目:给定两个整数 nk,返回 1 到 n 中所有可能的 k 个数字的组合。

LeetCode 链接Combinations

Python 实现

def combine(n, k):
    def backtrack(start, path):
        if len(path) == k:
            result.append(path[:])
            return

        for i in range(start, n + 1):
            path.append(i)
            backtrack(i + 1, path)
            path.pop()

    result = []
    backtrack(1, [])
    return result

# 使用示例
n = 4
k = 2
print(combine(n, k))  # 输出: [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

详解

  • 使用回溯算法生成所有可能的组合。时间复杂度为 O(C(n, k)),空间复杂度为 O(C(n, k) * k),其中 C(n, k) 是组合数。

78. 子集(Subsets)

题目:给定一个整数数组 nums,返回所有可能的子集(幂集)。

LeetCode 链接Subsets

Python 实现

def subsets(nums):
    result = []

    def backtrack(start, path):
        result.append(path[:])
        for i in range(start, len(nums)):
            path.append(nums[i])
            backtrack(i + 1, path)
            path.pop()

    backtrack(0, [])
    return result

# 使用示例
nums = [1, 2, 3]
print(subsets(nums))  # 输出: [[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]

详解

  • 使用回溯算法生成所有可能的子集。时间复杂度为 O(2^n),空间复杂度为 O(2^n * n)。

题目:给定一个二维网格和一个单词,检查网格中是否存在该单词。单词可以在网格中水平、垂直或对角线方向上存在。

LeetCode 链接Word Search

Python 实现

def exist(board, word):
    def dfs(i, j, index):
        if index == len(word):
            return True
        if (i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or 
            board[i][j] != word[index]):
            return False

        temp, board[i][j] = board[i][j], '#'
        found = (dfs(i + 1, j, index + 1) or
                 dfs(i - 1, j, index + 1) or
                 dfs(i, j + 1, index + 1) or
                 dfs(i, j - 1, index + 1))
        board[i][j] = temp

        return found

    for i in range(len(board)):
        for j in range(len(board[0])):
            if dfs(i, j, 0):
                return True
    return False

# 使用示例
board = [
    ['A', 'B', 'C', 'E'],
    ['S', 'F', 'C', 'S'],
    ['A', 'D', 'E', 'E']
]
word = "ABCCED"
print(exist(board, word))  # 输出: True

详解

  • 使用深度优先搜索(DFS)来检查单词是否存在于网格中。时间复杂度为 O(m * n * 4^L),空间复杂度为 O(L),其中 L 为单词长度。

80. 删除重复排序数组中的重复项 II(Remove Duplicates from Sorted Array II)

题目:给定一个排序数组 nums,删除重复项,使得每个元素最多出现两次,并返回新数组的长度。

LeetCode 链接Remove Duplicates from Sorted Array II

Python 实现

def remove_duplicates(nums):
    if not nums:
        return 0

    i = 1
    count = 1

    for j in range(1, len(nums)):
        if nums[j] == nums[j - 1]:
            count += 1
        else:
            count = 1

        if count <= 2:
            nums[i] = nums[j]
            i += 1

    return i

# 使用示例
nums = [1, 1, 1, 2, 2, 3]
length = remove_duplicates(nums)
print(nums[:length])  # 输出: [1, 1, 2, 2, 3]

详解

  • 使用双指针来确保每个元素最多出现两次。时间复杂度为 O(n),空间复杂度为 O(1)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖不同的算法和数据结构。

81. 搜索旋转排序数组 II(Search in Rotated Sorted Array II)

题目:给定一个可能包含重复元素的升序数组 nums 和一个目标值 target,搜索目标值是否存在于数组中。你必须实现一个时间复杂度为 O(log n) 的算法。

LeetCode 链接Search in Rotated Sorted Array II

Python 实现

def search(nums, target):
    left, right = 0, len(nums) - 1

    while left <= right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return True

        if nums[left] < nums[mid] or nums[mid] < nums[right]:  # 左侧有序
            if nums[left] <= target < nums[mid]:
                right = mid - 1
            else:
                left = mid + 1
        elif nums[mid] > nums[right] or nums[left] > nums[mid]:  # 右侧有序
            if nums[mid] < target <= nums[right]:
                left = mid + 1
            else:
                right = mid - 1
        else:
            left += 1

    return False

# 使用示例
nums = [2, 5, 6, 0, 0, 1, 2]
target = 0
print(search(nums, target))  # 输出: True

详解

  • 使用二分查找算法,但需要处理重复元素的情况。时间复杂度为 O(n),空间复杂度为 O(1)。

82. 删除排序链表中的重复元素 II(Remove Duplicates from Sorted List II)

题目:给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中没有重复的数字。

LeetCode 链接Remove Duplicates from Sorted List II

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def delete_duplicates(head):
    dummy = ListNode(0)
    dummy.next = head
    prev = dummy

    while head:
        if head.next and head.val == head.next.val:
            while head.next and head.val == head.next.val:
                head = head.next
            prev.next = head.next
        else:
            prev = prev.next
        head = head.next

    return dummy.next

# 使用示例
# 链表: 1 -> 2 -> 3 -> 3 -> 4 -> 4 -> 5
# 输出: 1 -> 5

详解

  • 使用哑节点和双指针来删除链表中的重复元素。时间复杂度为 O(n),空间复杂度为 O(1)。

83. 删除排序链表中的重复元素(Remove Duplicates from Sorted List)

题目:给定一个排序链表,删除所有重复的元素,使每个元素只出现一次。

LeetCode 链接Remove Duplicates from Sorted List

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def delete_duplicates(head):
    current = head
    while current and current.next:
        if current.val == current.next.val:
            current.next = current.next.next
        else:
            current = current.next
    return head

# 使用示例
# 链表: 1 -> 1 -> 2 -> 3 -> 3
# 输出: 1 -> 2 -> 3

详解

  • 直接遍历链表并删除重复节点。时间复杂度为 O(n),空间复杂度为 O(1)。

84. 柱状图中最大的矩形(Largest Rectangle in Histogram)

题目:给定一个整数数组 heights,每个元素表示柱状图的高度,求柱状图中能够形成的最大矩形的面积。

LeetCode 链接Largest Rectangle in Histogram

Python 实现

def largestRectangleArea(heights):
    stack = []
    max_area = 0
    heights.append(0)

    for i, h in enumerate(heights):
        while stack and heights[stack[-1]] > h:
            height = heights[stack.pop()]
            width = i if not stack else i - stack[-1] - 1
            max_area = max(max_area, height * width)
        stack.append(i)

    return max_area

# 使用示例
heights = [2, 1, 5, 6, 2, 3]
print(largestRectangleArea(heights))  # 输出: 10

详解

  • 使用栈来跟踪柱子的索引,从而计算每个柱子作为最矮柱子的最大矩形面积。时间复杂度为 O(n),空间复杂度为 O(n)。

85. 最大矩形(Maximal Rectangle)

题目:给定一个由 '0''1' 组成的二维矩阵,找到其中由 '1' 组成的最大矩形的面积。

LeetCode 链接Maximal Rectangle

Python 实现

def maximalRectangle(matrix):
    if not matrix or not matrix[0]:
        return 0

    def maximal_histogram_area(heights):
        stack = []
        max_area = 0
        heights.append(0)

        for i, h in enumerate(heights):
            while stack and heights[stack[-1]] > h:
                height = heights[stack.pop()]
                width = i if not stack else i - stack[-1] - 1
                max_area = max(max_area, height * width)
            stack.append(i)

        return max_area

    max_area = 0
    heights = [0] * len(matrix[0])

    for row in matrix:
        for j in range(len(row)):
            heights[j] = heights[j] + 1 if row[j] == '1' else 0
        max_area = max(max_area, maximal_histogram_area(heights))

    return max_area

# 使用示例
matrix = [
    ["1","0","1","0","0"],
    ["1","0","1","1","1"],
    ["1","1","1","1","1"],
    ["1","0","0","1","0"]
]
print(maximalRectangle(matrix))  # 输出: 6

详解

  • 先将二维矩阵转换为一维柱状图,然后使用最大矩形面积算法。时间复杂度为 O(m * n),空间复杂度为 O(n)。

86. 分隔链表(Partition List)

题目:给定一个链表和一个值 x,将链表中所有小于 x 的节点移到链表的左侧,所有大于或等于 x 的节点移到链表的右侧。

LeetCode 链接Partition List

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def partition(head, x):
    before_head = ListNode(0)
    after_head = ListNode(0)
    before, after = before_head, after_head

    while head:
        if head.val < x:
            before.next = head
            before = before.next
        else:
            after.next = head
            after = after.next
        head = head.next

    after.next = None
    before.next = after_head.next

    return before_head.next

# 使用示例
# 链表: 1 -> 4 -> 3 -> 2 -> 5 -> 2
# x = 3
# 输出: 1 -> 2 -> 2 -> 4 -> 3 -> 5

详解

  • 使用两个链表分别存储小于 x 和大于等于 x 的节点,最后连接两个链表。时间复杂度为 O(n),空间复杂度为 O(1)。

87. 扰乱字符串(Scramble String)

题目:给定两个字符串 s1s2,检查 s2 是否是 s1 的扰乱字符串。扰乱字符串是通过对 s1 的字符进行任意次数的交换得到的。

LeetCode 链接Scramble String

Python 实现

def is_scramble(s1, s2):
    if len(s1) != len(s2):
        return False
    if s1 == s2:
        return True
    if sorted(s1) != sorted(s2):
        return False

    n = len(s1)
    dp = [[[False] * n for _ in range(n)] for _ in range(n + 1)]

    for i in range(n):
        for j in range(n):
            dp[1][i][j] = s1[i] == s2[j]

    for length in range(2, n + 1):
        for i in range(n - length + 1):
            for j in range(n - length + 1):
                for k in range(1, length):
                    if (dp[k][i][j] and dp[length - k][i + k][j + k]) or (dp[k][i][j + length - k] and dp[length - k][i + k][j]):
                        dp[length][i][j] = True
                        break

    return dp[n][0][0]

# 使用示例
s1 = "great"
s2 = "rgeat"
print(is_scramble(s1, s2))  # 输出: True

详解

  • 使用动态规划算法来判断是否可以通过交换得到扰乱字符串。时间复杂度为 O(n^4),空间复杂度为 O(n^3)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖各种算法和数据结构的应用。

88. 合并两个有序数组(Merge Sorted Array)

题目:给定两个有序整数数组 nums1nums2,将 nums2 合并到 nums1 中,使得 nums1 成为一个有序数组。初始化 nums1nums2 的长度分别为 mnnums1 的大小为 m + n,其中前 m 个元素是 nums1 的有效部分,后 n 个元素是 nums1 的空闲部分。

LeetCode 链接Merge Sorted Array

Python 实现

def merge(nums1, m, nums2, n):
    while m > 0 and n > 0:
        if nums1[m - 1] > nums2[n - 1]:
            nums1[m + n - 1] = nums1[m - 1]
            m -= 1
        else:
            nums1[m + n - 1] = nums2[n - 1]
            n -= 1

    if n > 0:
        nums1[:n] = nums2[:n]

# 使用示例
nums1 = [1, 2, 3, 0, 0, 0]
m = 3
nums2 = [2, 5, 6]
n = 3
merge(nums1, m, nums2, n)
print(nums1)  # 输出: [1, 2, 2, 3, 5, 6]

详解

  • 从数组的尾部开始合并,避免覆盖 nums1 中的有效部分。时间复杂度为 O(m + n),空间复杂度为 O(1)。

89. 格雷编码(Gray Code)

题目:格雷编码是二进制数字的一种编码方式,其中两个连续的数字之间仅有一位不同。给定一个整数 n,返回 n 位格雷编码的序列。

LeetCode 链接Gray Code

Python 实现

def grayCode(n):
    result = [0]
    for i in range(n):
        result += [x + (1 << i) for x in reversed(result)]
    return result

# 使用示例
n = 2
print(grayCode(n))  # 输出: [0, 1, 3, 2]

详解

  • 通过逐位添加生成格雷编码序列。时间复杂度为 O(2^n),空间复杂度为 O(2^n)。

90. 子集 II(Subsets II)

题目:给定一个可能包含重复数字的整数数组 nums,返回所有唯一的子集(幂集)。

LeetCode 链接Subsets II

Python 实现

def subsetsWithDup(nums):
    def backtrack(start, path):
        result.append(path[:])
        for i in range(start, len(nums)):
            if i > start and nums[i] == nums[i - 1]:
                continue
            path.append(nums[i])
            backtrack(i + 1, path)
            path.pop()

    nums.sort()
    result = []
    backtrack(0, [])
    return result

# 使用示例
nums = [1, 2, 2]
print(subsetsWithDup(nums))  # 输出: [[], [1], [1, 2], [1, 2, 2], [2], [2, 2]]

详解

  • 使用回溯算法生成唯一的子集,并避免重复。时间复杂度为 O(2^n),空间复杂度为 O(2^n * n)。

91. 解码方法(Decode Ways)

题目:给定一个只包含数字的字符串 s,计算有多少种不同的方法可以解码这个字符串,其中 'A' 到 'Z' 映射到 '1' 到 '26'。

LeetCode 链接Decode Ways

Python 实现

def numDecodings(s):
    if not s or s[0] == '0':
        return 0

    n = len(s)
    dp = [0] * (n + 1)
    dp[0] = dp[1] = 1

    for i in range(2, n + 1):
        one_digit = int(s[i - 1])
        two_digits = int(s[i - 2:i])

        if one_digit >= 1:
            dp[i] += dp[i - 1]
        if 10 <= two_digits <= 26:
            dp[i] += dp[i - 2]

    return dp[n]

# 使用示例
s = "226"
print(numDecodings(s))  # 输出: 3

详解

  • 使用动态规划算法计算不同的解码方法。时间复杂度为 O(n),空间复杂度为 O(n)。

92. 反转链表 II(Reverse Linked List II)

题目:给定一个链表和两个整数 mn,反转链表从位置 m 到位置 n 的部分,返回修改后的链表。

LeetCode 链接Reverse Linked List II

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def reverse_between(head, m, n):
    if not head or m == n:
        return head

    dummy = ListNode(0)
    dummy.next = head
    pre = dummy

    for _ in range(m - 1):
        pre = pre.next

    start = pre.next
    then = start.next

    for _ in range(n - m):
        start.next = then.next
        then.next = pre.next
        pre.next = then
        then = start.next

    return dummy.next

# 使用示例
# 链表: 1 -> 2 -> 3 -> 4 -> 5
# m = 2, n = 4
# 输出: 1 -> 4 -> 3 -> 2 -> 5

详解

  • 通过遍历链表和重新连接节点来反转部分链表。时间复杂度为 O(n),空间复杂度为 O(1)。

93. 邻接矩阵中的有向图(Graph Valid Tree)

题目:给定一个包含 n 个节点和一个边列表 edges 的图,确定这个图是否是一个有效的树。有效的树必须是连通的且无环的。

LeetCode 链接Graph Valid Tree

Python 实现

from collections import defaultdict, deque

def validTree(n, edges):
    if len(edges) != n - 1:
        return False

    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)

    visited = set()

    def bfs(start):
        queue = deque([start])
        visited.add(start)

        while queue:
            node = queue.popleft()
            for neighbor in graph[node]:
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.append(neighbor)

    bfs(0)

    return len(visited) == n

# 使用示例
n = 5
edges = [[0, 1], [0, 2], [0, 3], [1, 4]]
print(validTree(n, edges))  # 输出: True

详解

  • 使用 BFS 检查图的连通性,同时检查边的数量是否符合树的性质。时间复杂度为 O(n),空间复杂度为 O(n)。

94. 二叉树的中序遍历(Binary Tree Inorder Traversal)

题目:给定一个二叉树,返回它的中序遍历。

LeetCode 链接Binary Tree Inorder Traversal

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def inorderTraversal(root):
    def inorder(node):
        if node:
            inorder(node.left)
            result.append(node.val)
            inorder(node.right)

    result = []
    inorder(root)
    return result

# 使用示例
# 二叉树:    1
#           / \
#          2   3
#         /
#        4
# 输出: [4, 2, 1, 3]

详解

  • 使用递归实现中序遍历。时间复杂度为 O(n),空间复杂度为 O(n)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖更多的算法和数据结构应用。

95. 不同的二叉搜索树 II(Unique Binary Search Trees II)

题目:给定一个整数 n,生成所有由 1n 组成的不同的二叉搜索树。

LeetCode 链接Unique Binary Search Trees II

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def generateTrees(n):
    def generate(start, end):
        if start > end:
            return [None]
        result = []
        for i in range(start, end + 1):
            left_trees = generate(start, i - 1)
            right_trees = generate(i + 1, end)
            for left in left_trees:
                for right in right_trees:
                    root = TreeNode(i)
                    root.left = left
                    root.right = right
                    result.append(root)
        return result

    if n == 0:
        return []
    return generate(1, n)

# 使用示例
n = 3
trees = generateTrees(n)
print(len(trees))  # 输出: 5

详解

  • 使用递归生成所有可能的二叉搜索树。时间复杂度为 O(C(n)),其中 C(n) 是第 n 个卡特兰数,空间复杂度为 O(C(n))。

96. 不同的二叉搜索树(Unique Binary Search Trees)

题目:给定一个整数 n,计算可以生成多少个不同的二叉搜索树。

LeetCode 链接Unique Binary Search Trees

Python 实现

def numTrees(n):
    dp = [0] * (n + 1)
    dp[0] = dp[1] = 1

    for i in range(2, n + 1):
        for j in range(i):
            dp[i] += dp[j] * dp[i - j - 1]

    return dp[n]

# 使用示例
n = 3
print(numTrees(n))  # 输出: 5

详解

  • 使用动态规划算法计算二叉搜索树的数量。时间复杂度为 O(n^2),空间复杂度为 O(n)。

97. 交错字符串(Interleaving String)

题目:给定三个字符串 s1s2s3,判断 s3 是否是由 s1s2 交错组成的。

LeetCode 链接Interleaving String

Python 实现

def isInterleave(s1, s2, s3):
    if len(s1) + len(s2) != len(s3):
        return False

    dp = [[False] * (len(s2) + 1) for _ in range(len(s1) + 1)]
    dp[0][0] = True

    for i in range(1, len(s1) + 1):
        dp[i][0] = dp[i - 1][0] and s1[i - 1] == s3[i - 1]

    for j in range(1, len(s2) + 1):
        dp[0][j] = dp[0][j - 1] and s2[j - 1] == s3[j - 1]

    for i in range(1, len(s1) + 1):
        for j in range(1, len(s2) + 1):
            dp[i][j] = (dp[i - 1][j] and s1[i - 1] == s3[i + j - 1]) or \
                       (dp[i][j - 1] and s2[j - 1] == s3[i + j - 1])

    return dp[len(s1)][len(s2)]

# 使用示例
s1 = "aabcc"
s2 = "dbbca"
s3 = "aadbbcbcac"
print(isInterleave(s1, s2, s3))  # 输出: True

详解

  • 使用动态规划算法来检查字符串是否可以交错组合。时间复杂度为 O(m * n),空间复杂度为 O(m * n)。

98. 验证二叉搜索树(Validate Binary Search Tree)

题目:给定一个二叉树,判断其是否为有效的二叉搜索树。

LeetCode 链接Validate Binary Search Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def isValidBST(root):
    def is_valid(node, low, high):
        if not node:
            return True
        if not (low < node.val < high):
            return False
        return is_valid(node.left, low, node.val) and is_valid(node.right, node.val, high)

    return is_valid(root, float('-inf'), float('inf'))

# 使用示例
# 二叉树:    2
#           / \
#          1   3
# 输出: True

详解

  • 通过递归检查每个节点是否满足二叉搜索树的条件。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

99. 恢复二叉搜索树(Recover Binary Search Tree)

题目:给定一个二叉搜索树,其中的两个节点被错误地交换了,恢复树使其成为一个有效的二叉搜索树。

LeetCode 链接Recover Binary Search Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def recoverTree(root):
    def inorder(node):
        if not node:
            return []
        return inorder(node.left) + [node] + inorder(node.right)

    nodes = inorder(root)
    x = y = pred = None

    for i in range(len(nodes)):
        if pred and nodes[i].val < pred.val:
            y = nodes[i]
            if not x:
                x = pred
            else:
                break
        pred = nodes[i]

    if x and y:
        x.val, y.val = y.val, x.val

# 使用示例
# 二叉树:    1
#           / \
#          3   2
# 输出: 二叉搜索树变为:    2
#                     / \
#                    1   3

详解

  • 通过中序遍历找到错误的节点并交换。时间复杂度为 O(n),空间复杂度为 O(n)。

100. 相同的树(Same Tree)

题目:给定两个二叉树,检查它们是否完全相同。

LeetCode 链接Same Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def isSameTree(p, q):
    if not p and not q:
        return True
    if not p or not q:
        return False
    return (p.val == q.val) and isSameTree(p.left, q.left) and isSameTree(p.right, q.right)

# 使用示例
# 二叉树1:    1        二叉树2:    1
#            / \                / \
#           2   3              2   3
# 输出: True

详解

  • 递归检查两个树的节点值和结构。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

101. 对称二叉树(Symmetric Tree)

题目:给定一个二叉树,检查它是否是对称的(即,左右子树互为镜像)。

LeetCode 链接Symmetric Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def isSymmetric(root):
    def is_mirror(t1, t2):
        if not t1 and not t2:
            return True
        if not t1 or not t2:
            return False
        return (t1.val == t2.val) and is_mirror(t1.right, t2.left) and is_mirror(t1.left, t2.right)

    return is_mirror(root, root)

# 使用示例
# 二叉树:    1
#           / \
#          2   2
#         / \ / \
#        3  4 4  3
# 输出: True

详解

  • 使用递归检查树的左右子树是否对称。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

102. 二叉树的层序遍历(Binary Tree Level Order Traversal)

题目:给定一个二叉树,返回其节点值的层序遍历(即逐层访问)。

LeetCode 链接Binary Tree Level Order Traversal

Python 实现

from collections import deque

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def levelOrder(root):
    if not root:
        return []

    result = []
    queue = deque([root])

    while queue:
        level = []
        for _ in range(len(queue)):
            node = queue.popleft()
            level.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        result.append(level)

    return result

# 使用示例
# 二叉树:    3
#           / \
#          9  20
#             /  \
#            15   7
# 输出: [[3], [9, 20], [15, 7]]

详解

  • 使用队列进行层序遍历。时间复杂度为 O(n),空间复杂度为 O(n)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涉及不同的数据结构和算法问题。

103. 二叉树的锯齿形层序遍历(Binary Tree Zigzag Level Order Traversal)

题目:给定一个二叉树,返回其节点值的锯齿形层序遍历(即逐层访问,但每层的顺序交替)。

LeetCode 链接Binary Tree Zigzag Level Order Traversal

Python 实现

from collections import deque

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def zigzagLevelOrder(root):
    if not root:
        return []

    result, level, zigzag = [], deque([root]), False

    while level:
        current_level, next_level = [], deque()
        while level:
            node = level.popleft()
            current_level.append(node.val)
            if node.left:
                next_level.append(node.left)
            if node.right:
                next_level.append(node.right)
        result.append(current_level if not zigzag else current_level[::-1])
        level, zigzag = next_level, not zigzag

    return result

# 使用示例
# 二叉树:    3
#           / \
#          9  20
#             /  \
#            15   7
# 输出: [[3], [20, 9], [15, 7]]

详解

  • 使用队列和布尔变量控制层序遍历的顺序。时间复杂度为 O(n),空间复杂度为 O(n)。

104. 二叉树的最大深度(Maximum Depth of Binary Tree)

题目:给定一个二叉树,返回其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点数。

LeetCode 链接Maximum Depth of Binary Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def maxDepth(root):
    if not root:
        return 0
    return max(maxDepth(root.left), maxDepth(root.right)) + 1

# 使用示例
# 二叉树:    3
#           / \
#          9  20
#             /  \
#            15   7
# 输出: 3

详解

  • 通过递归计算左右子树的深度并取最大值。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

105. 从前序与中序遍历序列构造二叉树(Construct Binary Tree from Preorder and Inorder Traversal)

题目:给定前序遍历和中序遍历的结果,构造二叉树。

LeetCode 链接Construct Binary Tree from Preorder and Inorder Traversal

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def buildTree(preorder, inorder):
    if not preorder or not inorder:
        return None

    root_val = preorder[0]
    root = TreeNode(root_val)
    root_index = inorder.index(root_val)

    root.left = buildTree(preorder[1:1 + root_index], inorder[:root_index])
    root.right = buildTree(preorder[1 + root_index:], inorder[root_index + 1:])

    return root

# 使用示例
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]
tree = buildTree(preorder, inorder)

详解

  • 通过前序遍历的第一个元素确定根节点,并利用中序遍历分割左右子树。时间复杂度为 O(n^2),空间复杂度为 O(n)。

106. 从中序与后序遍历序列构造二叉树(Construct Binary Tree from Inorder and Postorder Traversal)

题目:给定中序遍历和后序遍历的结果,构造二叉树。

LeetCode 链接Construct Binary Tree from Inorder and Postorder Traversal

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def buildTree(inorder, postorder):
    if not inorder or not postorder:
        return None

    root_val = postorder[-1]
    root = TreeNode(root_val)
    root_index = inorder.index(root_val)

    root.left = buildTree(inorder[:root_index], postorder[:root_index])
    root.right = buildTree(inorder[root_index + 1:], postorder[root_index:-1])

    return root

# 使用示例
inorder = [9, 3, 15, 20, 7]
postorder = [9, 15, 7, 20, 3]
tree = buildTree(inorder, postorder)

详解

  • 通过后序遍历的最后一个元素确定根节点,并利用中序遍历分割左右子树。时间复杂度为 O(n^2),空间复杂度为 O(n)。

107. 二叉树的层序遍历 II(Binary Tree Level Order Traversal II)

题目:给定一个二叉树,返回其节点值的层序遍历的逆序(即自底向上的层序遍历)。

LeetCode 链接Binary Tree Level Order Traversal II

Python 实现

from collections import deque

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def levelOrderBottom(root):
    if not root:
        return []

    result, level = [], deque([root])

    while level:
        current_level = []
        for _ in range(len(level)):
            node = level.popleft()
            current_level.append(node.val)
            if node.left:
                level.append(node.left)
            if node.right:
                level.append(node.right)
        result.insert(0, current_level)

    return result

# 使用示例
# 二叉树:    3
#           / \
#          9  20
#             /  \
#            15   7
# 输出: [[15, 7], [9, 20], [3]]

详解

  • 使用队列进行层序遍历,并在结果中插入每层的节点值。时间复杂度为 O(n),空间复杂度为 O(n)。

108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree)

题目:将一个有序数组转换为一个高度平衡的二叉搜索树。

LeetCode 链接Convert Sorted Array to Binary Search Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def sortedArrayToBST(nums):
    def convert(left, right):
        if left > right:
            return None
        mid = (left + right) // 2
        root = TreeNode(nums[mid])
        root.left = convert(left, mid - 1)
        root.right = convert(mid + 1, right)
        return root

    return convert(0, len(nums) - 1)

# 使用示例
nums = [-10, -3, 0, 5, 9]
tree = sortedArrayToBST(nums)

详解

  • 使用递归将有序数组转换为平衡的二叉搜索树。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

109. 有序链表转换为二叉搜索树(Convert Sorted List to Binary Search Tree)

题目:给定一个按升序排列的链表,将其转换为高度平衡的二叉搜索树。

LeetCode 链接Convert Sorted List to Binary Search Tree

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def sortedListToBST(head):
    def findMiddle(left, right):
        slow, fast = left, left
        while fast != right and fast.next != right:
            slow = slow.next
            fast = fast.next
            fast = fast.next
        return slow

    def convert(left, right):
        if left == right:
            return None
        mid = findMiddle(left, right)
        root = TreeNode(mid.val)
        root.left = convert(left, mid)
        root.right = convert(mid.next, right)
        return root

    return convert(head, None)

# 使用示例
# 链表: -10 -> -3 -> 0 -> 5 -> 9
# 输出: 二叉搜索树

详解

  • 通过递归构造二叉搜索树,使用快慢指针找到中间节点。时间复杂度为 O(n),空间复杂度为 O(log n)(递归栈的深度)。

110. 平衡二叉树(Balanced Binary Tree)

题目:给定一个二叉树,判断其是否为平衡二叉树。平衡二叉树的定义是:每个节点的左右子树的高度差的绝对值不超过 1。

LeetCode 链接Balanced Binary Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def isBalanced(root):
    def check_height(node):
        if not node:
            return 0
        left_height = check_height(node.left)
        right_height = check_height(node.right)
        if left_height == -1 or right_height == -1 or abs(left_height - right_height) > 1:
            return -1
        return max(left_height, right_height) + 1

    return check_height(root) != -1

# 使用示例
# 二叉树:    3
#           / \
#          9  20
#             /  \
#            15   7
# 输出: True

详解

  • 使用递归检查每个节点的左右子树的高度差。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖更广泛的算法和数据结构应用。

111. 二叉树的最小深度(Minimum Depth of Binary Tree)

题目:给定一个二叉树,返回其最小深度。最小深度是指从根节点到最近的叶子节点的路径上的节点数。

LeetCode 链接Minimum Depth of Binary Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def minDepth(root):
    if not root:
        return 0
    if not root.left and not root.right:
        return 1
    if not root.left:
        return minDepth(root.right) + 1
    if not root.right:
        return minDepth(root.left) + 1
    return min(minDepth(root.left), minDepth(root.right)) + 1

# 使用示例
# 二叉树:    3
#           / \
#          9  20
#             /  \
#            15   7
# 输出: 2

详解

  • 使用递归计算每个节点的最小深度。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

112. 路径总和(Path Sum)

题目:给定一个二叉树和一个目标和,判断树中是否存在从根节点到叶子节点的路径,使得路径上的所有节点值之和等于目标和。

LeetCode 链接Path Sum

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def hasPathSum(root, targetSum):
    if not root:
        return False
    if not root.left and not root.right:
        return root.val == targetSum
    targetSum -= root.val
    return hasPathSum(root.left, targetSum) or hasPathSum(root.right, targetSum)

# 使用示例
# 二叉树:    5
#           / \
#          4   8
#         /   / \
#        11  13  4
#       /  \      \
#      7    2      1
# 输出: True (5 -> 4 -> 11 -> 2)

详解

  • 使用递归检查每个路径的节点值之和。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

113. 路径总和 II(Path Sum II)

题目:给定一个二叉树和一个目标和,返回所有从根节点到叶子节点的路径,使得路径上的所有节点值之和等于目标和。

LeetCode 链接Path Sum II

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def pathSum(root, targetSum):
    def dfs(node, current_path, target):
        if not node:
            return
        current_path.append(node.val)
        if not node.left and not node.right and sum(current_path) == target:
            result.append(list(current_path))
        else:
            dfs(node.left, current_path, target)
            dfs(node.right, current_path, target)
        current_path.pop()

    result = []
    dfs(root, [], targetSum)
    return result

# 使用示例
# 二叉树:    5
#           / \
#          4   8
#         /   / \
#        11  13  4
#       /  \      \
#      7    2      1
# 输出: [[5, 4, 11, 2], [5, 8, 4, 1]]

详解

  • 使用深度优先搜索(DFS)查找所有符合条件的路径。时间复杂度为 O(n),空间复杂度为 O(h)。

114. 二叉树展开为链表(Flatten Binary Tree to Linked List)

题目:给定一个二叉树,将其展开为链表,使得链表的前序遍历与二叉树的前序遍历一致。

LeetCode 链接Flatten Binary Tree to Linked List

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def flatten(root):
    def flatten_tree(node):
        if not node:
            return None
        if not node.left and not node.right:
            return node
        left_tail = flatten_tree(node.left)
        right_tail = flatten_tree(node.right)

        if node.left:
            left_tail.right = node.right
            node.right = node.left
            node.left = None

        return right_tail if right_tail else left_tail

    flatten_tree(root)

# 使用示例
# 二叉树:    1
#           / \
#          2   5
#         / \   \
#        3   4   6
# 输出: 1 -> 2 -> 3 -> 4 -> 5 -> 6

详解

  • 递归地展开二叉树为链表。时间复杂度为 O(n),空间复杂度为 O(h)。

115. 不同的子序列(Distinct Subsequences)

题目:给定一个字符串 s 和一个字符串 t,计算 ts 中出现的不同子序列的数量。

LeetCode 链接Distinct Subsequences

Python 实现

def numDistinct(s, t):
    m, n = len(s), len(t)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for j in range(n + 1):
        dp[0][j] = 0
    for i in range(m + 1):
        dp[i][0] = 1

    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if s[i - 1] == t[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]
            else:
                dp[i][j] = dp[i - 1][j]

    return dp[m][n]

# 使用示例
s = "rabbbit"
t = "rabbit"
print(numDistinct(s, t))  # 输出: 3

详解

  • 使用动态规划计算子序列的数量。时间复杂度为 O(m * n),空间复杂度为 O(m * n)。

116. 填充每个节点的下一个右侧节点指针(Populating Next Right Pointers in Each Node)

题目:给定一个完美二叉树,填充每个节点的下一个右侧节点指针,使其指向右侧的节点。如果没有右侧节点,则填充 null

LeetCode 链接Populating Next Right Pointers in Each Node

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None, next=None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next

def connect(root):
    if not root:
        return root

    def connect_two_nodes(node1, node2):
        if not node1 or not node2:
            return
        node1.next = node2
        connect_two_nodes(node1.left, node1.right)
        connect_two_nodes(node2.left, node2.right)
        connect_two_nodes(node1.right, node2.left)

    connect_two_nodes(root.left, root.right)
    return root

# 使用示例
# 二叉树:    1
#           / \
#          2   3
#         / \ / \
#        4  5 6  7
# 输出: 每个节点的 next 指针被正确填充

详解

  • 使用递归连接相邻的节点。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

118. 杨辉三角(Pascal's Triangle)

题目:给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。

LeetCode 链接Pascal's Triangle

Python 实现

def generate(numRows):
    result = []
    for i in range(numRows):
        row = [1] * (i + 1)
        for j in range(1, i):
            row[j] = result[i - 1][j - 1] + result[i - 1][j]
        result.append(row)
    return result

# 使用示例
print(generate(5))  # 输出: [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]

详解

  • 通过动态生成每一行的值。时间复杂度为 O(numRows^2),空间复杂度为 O(numRows^2)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涉及更复杂的算法和数据结构问题。

119. 杨辉三角 II(Pascal's Triangle II)

题目:给定一个非负整数 rowIndex,返回杨辉三角中第 rowIndex 行的元素(索引从 0 开始)。

LeetCode 链接Pascal's Triangle II

Python 实现

def getRow(rowIndex):
    row = [1]
    for i in range(1, rowIndex + 1):
        row.append(row[-1] * (rowIndex - i + 1) // i)
    return row

# 使用示例
print(getRow(3))  # 输出: [1, 3, 3, 1]

详解

  • 利用杨辉三角的性质直接计算每一行的元素,避免了生成整个三角形。时间复杂度为 O(rowIndex),空间复杂度为 O(rowIndex)。

121. 买卖股票的最佳时机(Best Time to Buy and Sell Stock)

题目:给定一个数组 prices,其中 prices[i] 是股票在第 i 天的价格。你可以在多次交易中只进行一次买卖,计算你能够获得的最大利润。

LeetCode 链接Best Time to Buy and Sell Stock

Python 实现

def maxProfit(prices):
    min_price = float('inf')
    max_profit = 0
    for price in prices:
        min_price = min(min_price, price)
        max_profit = max(max_profit, price - min_price)
    return max_profit

# 使用示例
print(maxProfit([7, 1, 5, 3, 6, 4]))  # 输出: 5

详解

  • 使用贪心算法,通过遍历计算最小价格和最大利润。时间复杂度为 O(n),空间复杂度为 O(1)。

122. 买卖股票的最佳时机 II(Best Time to Buy and Sell Stock II)

题目:给定一个数组 prices,其中 prices[i] 是股票在第 i 天的价格。你可以在多次交易中进行多次买卖,计算你能够获得的最大利润。

LeetCode 链接Best Time to Buy and Sell Stock II

Python 实现

def maxProfit(prices):
    total_profit = 0
    for i in range(1, len(prices)):
        if prices[i] > prices[i - 1]:
            total_profit += prices[i] - prices[i - 1]
    return total_profit

# 使用示例
print(maxProfit([7, 1, 5, 3, 6, 4]))  # 输出: 7

详解

  • 贪心算法,通过找出每次价格上涨的区间来计算总利润。时间复杂度为 O(n),空间复杂度为 O(1)。

124. 二叉树中的最大路径和(Binary Tree Maximum Path Sum)

题目:给定一个非空二叉树,计算其最大路径和。路径的定义是:从任何节点出发,沿着父节点到子节点的路径可以重新开始。

LeetCode 链接Binary Tree Maximum Path Sum

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def maxPathSum(root):
    def helper(node):
        nonlocal max_sum
        if not node:
            return 0
        left = max(helper(node.left), 0)
        right = max(helper(node.right), 0)
        max_sum = max(max_sum, node.val + left + right)
        return node.val + max(left, right)

    max_sum = float('-inf')
    helper(root)
    return max_sum

# 使用示例
# 二叉树:    1
#           / \
#          2   3
# 输出: 6 (2 -> 1 -> 3)

详解

  • 使用递归计算每个节点的最大路径和,并更新全局最大值。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

126. 单词接龙 II(Word Ladder II)

题目:给定两个单词 beginWordendWord 以及一个字典 wordList,找到所有从 beginWordendWord 的最短转换序列。每次转换只能改变一个字母,并且每个转换后的单词必须在字典中。

LeetCode 链接Word Ladder II

Python 实现

from collections import defaultdict, deque

def findLadders(beginWord, endWord, wordList):
    def add_to_graph(word):
        for i in range(len(word)):
            pattern = word[:i] + "*" + word[i+1:]
            graph[pattern].append(word)

    def bfs():
        queue = deque([(beginWord, [beginWord])])
        visited = set([beginWord])
        while queue:
            word, path = queue.popleft()
            if word == endWord:
                results.append(path)
                continue
            for i in range(len(word)):
                pattern = word[:i] + "*" + word[i+1:]
                for neighbor in graph[pattern]:
                    if neighbor not in visited:
                        visited.add(neighbor)
                        queue.append((neighbor, path + [neighbor]))

    graph = defaultdict(list)
    wordList.add(beginWord)
    wordList.add(endWord)
    for word in wordList:
        add_to_graph(word)

    results = []
    bfs()
    return results

# 使用示例
beginWord = "hit"
endWord = "cog"
wordList = set(["hot","dot","dog","lot","log","cog"])
print(findLadders(beginWord, endWord, wordList))

详解

  • 使用广度优先搜索(BFS)和图的邻接表表示单词转换。时间复杂度为 O(N * M^2),空间复杂度为 O(N * M),其中 N 为字典大小,M 为单词长度。

130. 被围绕的区域(Surrounded Regions)

题目:给定一个二维矩阵,包含 'X''O'。如果一个区域(被 'X' 包围的区域)中的所有 'O' 都被 'X' 包围,则该区域的 'O' 将被替换为 'X'

LeetCode 链接Surrounded Regions

Python 实现

def solve(board):
    if not board or not board[0]:
        return

    def dfs(x, y):
        if x < 0 or x >= len(board) or y < 0 or y >= len(board[0]) or board[x][y] != 'O':
            return
        board[x][y] = '#'
        for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
            dfs(x + dx, y + dy)

    rows, cols = len(board), len(board[0])
    for i in range(rows):
        dfs(i, 0)
        dfs(i, cols - 1)
    for j in range(cols):
        dfs(0, j)
        dfs(rows - 1, j)

    for i in range(rows):
        for j in range(cols):
            if board[i][j] == 'O':
                board[i][j] = 'X'
            elif board[i][j] == '#':
                board[i][j] = 'O'

# 使用示例
board = [
    ["X","X","X","X"],
    ["X","O","O","X"],
    ["X","X","O","X"],
    ["X","O","X","X"]
]
solve(board)
# 输出: [["X","X","X","X"], ["X","X","X","X"], ["X","X","X","X"], ["X","O","X","X"]]

详解

  • 使用深度优先搜索(DFS)标记未被包围的 'O',然后替换被包围的 'O''X'。时间复杂度为 O(m * n),空间复杂度为 O(m * n),其中 m 和 n 分别为矩阵的行和列数。

137. 只出现一次的数字 II(Single Number II)

题目:给定一个整数数组 nums,每个元素出现三次,除了一个元素只出现一次。找出只出现一次的那个元素。

LeetCode 链接Single Number II

Python 实现

def singleNumber(nums):
    ones, twos = 0, 0
    for num in nums:
        ones = (ones ^ num) & ~twos
        twos = (twos ^ num) & ~ones
    return ones

# 使用示例
print(singleNumber([2, 2, 3, 2]))  # 输出: 3

详解

  • 使用位运算来追踪出现次数。时间复杂度为 O(n),空间复杂度为 O(1)。

继续介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖更复杂的算法和数据结构应用。

138. 复制带随机指针的链表(Copy List with Random Pointer)

题目:给定一个链表中的每个节点包含一个随机指针,随机指针可以指向链表中的任何节点或 null。复制链表并返回新链表的头节点。

LeetCode 链接Copy List with Random Pointer

Python 实现

class Node:
    def __init__(self, val=0, next=None, random=None):
        self.val = val
        self.next = next
        self.random = random

def copyRandomList(head):
    if not head:
        return None

    # Step 1: Copy each node and insert it right next to the original node
    current = head
    while current:
        new_node = Node(current.val, current.next)
        current.next = new_node
        current = new_node.next

    # Step 2: Copy the random pointers
    current = head
    while current:
        new_node = current.next
        new_node.random = current.random.next if current.random else None
        current = new_node.next

    # Step 3: Separate the copied list from the original list
    dummy = Node(0)
    copy_current, current = dummy, head
    while current:
        copy_current.next = current.next
        copy_current = copy_current.next
        current.next = copy_current.next
        current = current.next

    return dummy.next

# 使用示例
# 链表结构:
# 1 -> 2 -> 3
# |    |    |
# v    v    v
# 2    1    3

详解

  • 通过三步操作来复制链表。时间复杂度为 O(n),空间复杂度为 O(1)(不包括返回的复制链表的空间)。

139. 单词拆分(Word Break)

题目:给定一个非空字符串 s 和一个单词字典 wordDict,判断 s 是否可以被空格拆分成一个或多个字典中出现的单词。

LeetCode 链接Word Break

Python 实现

def wordBreak(s, wordDict):
    wordSet = set(wordDict)
    dp = [False] * (len(s) + 1)
    dp[0] = True

    for i in range(1, len(s) + 1):
        for j in range(i):
            if dp[j] and s[j:i] in wordSet:
                dp[i] = True
                break

    return dp[-1]

# 使用示例
s = "leetcode"
wordDict = ["leet", "code"]
print(wordBreak(s, wordDict))  # 输出: True

详解

  • 使用动态规划检查是否可以用字典中的单词分解字符串。时间复杂度为 O(n^2),空间复杂度为 O(n)。

141. 环形链表(Linked List Cycle)

题目:给定一个链表,判断链表中是否有环。

LeetCode 链接Linked List Cycle

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def hasCycle(head):
    slow, fast = head, head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            return True
    return False

# 使用示例
# 链表: 3 -> 2 -> 0 -> -4 (环形: -4 -> 2)

详解

  • 使用快慢指针(Floyd 判圈算法)检测链表是否有环。时间复杂度为 O(n),空间复杂度为 O(1)。

142. 环形链表 II(Linked List Cycle II)

题目:给定一个链表,返回链表中环的入口节点。如果链表中没有环,返回 null

LeetCode 链接Linked List Cycle II

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def detectCycle(head):
    slow, fast = head, head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            entry = head
            while entry != slow:
                entry = entry.next
                slow = slow.next
            return entry
    return None

# 使用示例
# 链表: 3 -> 2 -> 0 -> -4 (环形: -4 -> 2)

详解

  • 通过检测环的入口节点。时间复杂度为 O(n),空间复杂度为 O(1)。

144. 二叉树的前序遍历(Binary Tree Preorder Traversal)

题目:给定一个二叉树,返回其前序遍历的节点值。

LeetCode 链接Binary Tree Preorder Traversal

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def preorderTraversal(root):
    result = []
    def traverse(node):
        if not node:
            return
        result.append(node.val)
        traverse(node.left)
        traverse(node.right)

    traverse(root)
    return result

# 使用示例
# 二叉树:    1
#           / \
#          2   3
# 输出: [1, 2, 3]

详解

  • 使用递归实现前序遍历。时间复杂度为 O(n),空间复杂度为 O(h),其中 h 为树的高度。

146. LRU 缓存(LRU Cache)

题目:设计并实现一个 LRU(Least Recently Used)缓存机制。实现 LRUCache 类,支持 getput 操作。

LeetCode 链接LRU Cache

Python 实现

from collections import OrderedDict

class LRUCache:
    def __init__(self, capacity: int):
        self.cache = OrderedDict()
        self.capacity = capacity

    def get(self, key: int) -> int:
        if key not in self.cache:
            return -1
        else:
            self.cache.move_to_end(key)
            return self.cache[key]

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            self.cache.move_to_end(key)
        elif len(self.cache) >= self.capacity:
            self.cache.popitem(last=False)
        self.cache[key] = value

# 使用示例
lru_cache = LRUCache(2)
lru_cache.put(1, 1)
lru_cache.put(2, 2)
print(lru_cache.get(1))  # 输出: 1
lru_cache.put(3, 3)     # 驱逐键 2
print(lru_cache.get(2))  # 输出: -1 (未找到)
lru_cache.put(4, 4)     # 驱逐键 1
print(lru_cache.get(1))  # 输出: -1 (未找到)
print(lru_cache.get(3))  # 输出: 3
print(lru_cache.get(4))  # 输出: 4

详解

  • 使用 OrderedDict 实现 LRU 缓存。时间复杂度为 O(1) 的 getput 操作。空间复杂度为 O(capacity)。

151. 翻转字符串里的单词(Reverse Words in a String)

题目:给定一个字符串 s,返回字符串中的单词以相反的顺序排列。单词之间用单个空格分隔。

LeetCode 链接Reverse Words in a String

Python 实现

def reverseWords(s):
    words = s.split()
    return ' '.join(reversed(words))

# 使用示例
print(reverseWords("the sky is blue"))  # 输出: "blue is sky the"

详解

  • 使用 Python 内置的 splitjoin 函数来处理字符串。时间复杂度为 O(n),空间复杂度为 O(n)。

继续为你介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖进阶算法和数据结构的应用。

152. 乘积最大子数组(Maximum Product Subarray)

题目:给你一个整数数组 nums,请找出数组中乘积最大的连续子数组(至少包含一个数字),并返回该子数组所对应的乘积。

LeetCode 链接Maximum Product Subarray

Python 实现

def maxProduct(nums):
    if not nums:
        return 0

    max_product = min_product = result = nums[0]

    for num in nums[1:]:
        if num < 0:
            max_product, min_product = min_product, max_product
        max_product = max(num, max_product * num)
        min_product = min(num, min_product * num)
        result = max(result, max_product)

    return result

# 使用示例
nums = [2, 3, -2, 4]
print(maxProduct(nums))  # 输出: 6

详解

  • 动态规划,维护两个变量 max_productmin_product 分别记录当前的最大值和最小值,遇到负数时交换这两个值。时间复杂度为 O(n),空间复杂度为 O(1)。

153. 寻找旋转排序数组中的最小值(Find Minimum in Rotated Sorted Array)

题目:假设按照升序排序的数组在预先未知的某个点上进行了旋转,请找出旋转后数组中的最小元素。

LeetCode 链接Find Minimum in Rotated Sorted Array

Python 实现

def findMin(nums):
    left, right = 0, len(nums) - 1

    while left < right:
        mid = (left + right) // 2
        if nums[mid] > nums[right]:
            left = mid + 1
        else:
            right = mid

    return nums[left]

# 使用示例
nums = [4, 5, 6, 7, 0, 1, 2]
print(findMin(nums))  # 输出: 0

详解

  • 使用二分查找法,在旋转数组中查找最小值。时间复杂度为 O(log n),空间复杂度为 O(1)。

198. 打家劫舍(House Robber)

题目:给定一个数组 nums 代表每个房屋中的金额,不能抢相邻的两户,返回能够抢劫到的最高金额。

LeetCode 链接House Robber

Python 实现

def rob(nums):
    if not nums:
        return 0
    if len(nums) == 1:
        return nums[0]

    prev2, prev1 = 0, nums[0]

    for i in range(1, len(nums)):
        curr = max(prev1, prev2 + nums[i])
        prev2, prev1 = prev1, curr

    return prev1

# 使用示例
nums = [2, 7, 9, 3, 1]
print(rob(nums))  # 输出: 12

详解

  • 动态规划,prev1 表示到达当前房屋时能抢到的最大金额,prev2 表示到达前一个房屋时的最大金额。时间复杂度为 O(n),空间复杂度为 O(1)。

200. 岛屿数量(Number of Islands)

题目:给定一个二维网格,'1' 表示陆地,'0' 表示水域,计算网格中有多少个岛屿。岛屿被水域分隔,且只能垂直或水平连接。

LeetCode 链接Number of Islands

Python 实现

def numIslands(grid):
    if not grid:
        return 0

    def dfs(i, j):
        if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]) or grid[i][j] == '0':
            return
        grid[i][j] = '0'
        dfs(i + 1, j)
        dfs(i - 1, j)
        dfs(i, j + 1)
        dfs(i, j - 1)

    count = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == '1':
                count += 1
                dfs(i, j)

    return count

# 使用示例
grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
print(numIslands(grid))  # 输出: 1

详解

  • 使用深度优先搜索(DFS)遍历每个岛屿,并将其所有陆地标记为已访问。时间复杂度为 O(mn),空间复杂度为 O(mn)。

207. 课程表(Course Schedule)

题目:给你 numCourses 门课程以及课程间的先修关系 prerequisites,判断是否可以完成所有课程。

LeetCode 链接Course Schedule

Python 实现

from collections import defaultdict, deque

def canFinish(numCourses, prerequisites):
    graph = defaultdict(list)
    indegree = [0] * numCourses

    for dest, src in prerequisites:
        graph[src].append(dest)
        indegree[dest] += 1

    queue = deque([i for i in range(numCourses) if indegree[i] == 0])
    count = 0

    while queue:
        course = queue.popleft()
        count += 1
        for neighbor in graph[course]:
            indegree[neighbor] -= 1
            if indegree[neighbor] == 0:
                queue.append(neighbor)

    return count == numCourses

# 使用示例
numCourses = 2
prerequisites = [[1, 0]]
print(canFinish(numCourses, prerequisites))  # 输出: True

详解

  • 使用拓扑排序(BFS)来检测是否存在环,判断能否完成所有课程。时间复杂度为 O(V + E),空间复杂度为 O(V + E)。

208. 实现 Trie(前缀树)(Implement Trie (Prefix Tree))

题目:实现一个 Trie(前缀树),包含插入、搜索、和判断是否有前缀等操作。

LeetCode 链接Implement Trie (Prefix Tree)

Python 实现

class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_end_of_word = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.is_end_of_word = True

    def search(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                return False
            node = node.children[char]
        return node.is_end_of_word

    def startsWith(self, prefix):
        node = self.root
        for char in prefix:
            if char not in node.children:
                return False
            node = node.children[char]
        return True

# 使用示例
trie = Trie()
trie.insert("apple")
print(trie.search("apple"))  # 输出: True
print(trie.startsWith("app"))  # 输出: True
print(trie.search("app"))  # 输出: False

详解

  • 前缀树的实现,支持高效的单词插入和前缀查找。插入、搜索和前缀判断的时间复杂度均为 O(m),m 是单词或前缀的长度。

215. 数组中的第 K 个最大元素(Kth Largest Element in an Array)

题目:给定一个未排序的数组,找到其中第 k 个最大的元素。

LeetCode 链接Kth Largest Element in an Array

Python 实现

import heapq

def findKthLargest(nums, k):
    return heapq.nlargest(k, nums)[-1]

# 使用示例
nums = [3, 2, 1, 5, 6, 4]
k = 2
print(findKthLargest(nums, k))  # 输出: 5

详解

  • 使用堆(heapq 库)找到第 k 大的元素。时间复杂度为 O(n log k),空间复杂度为 O(k)。

继续为你介绍更多经典的 LeetCode 题目及其 Python 实现,涵盖广泛的算法与数据结构,帮助你提升编程技能。

221. 最大正方形(Maximal Square)

题目:在一个由 0 和 1 组成的二维矩阵中,找到只包含 1 的最大正方形,并返回其面积。

LeetCode 链接Maximal Square

Python 实现

def maximalSquare(matrix):
    if not matrix:
        return 0

    rows, cols = len(matrix), len(matrix[0])
    dp = [[0] * (cols + 1) for _ in range(rows + 1)]
    max_side = 0

    for i in range(1, rows + 1):
        for j in range(1, cols + 1):
            if matrix[i - 1][j - 1] == '1':
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1
                max_side = max(max_side, dp[i][j])

    return max_side * max_side

# 使用示例
matrix = [
    ["1","0","1","0","0"],
    ["1","0","1","1","1"],
    ["1","1","1","1","1"],
    ["1","0","0","1","0"]
]
print(maximalSquare(matrix))  # 输出: 4

详解

  • 使用动态规划构造辅助表 dp,每个 dp[i][j] 记录以 (i, j) 为右下角的最大正方形的边长。时间复杂度为 O(mn),空间复杂度为 O(mn)。

234. 回文链表(Palindrome Linked List)

题目:给定一个单链表,判断其是否为回文链表。

LeetCode 链接Palindrome Linked List

Python 实现

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def isPalindrome(head):
    fast = slow = head
    prev = None

    # 找到中间节点
    while fast and fast.next:
        fast = fast.next.next
        next_slow = slow.next
        slow.next = prev
        prev = slow
        slow = next_slow

    if fast:
        slow = slow.next

    # 比较前后两部分
    while prev and slow:
        if prev.val != slow.val:
            return False
        prev = prev.next
        slow = slow.next

    return True

# 使用示例
# 链表:1 -> 2 -> 2 -> 1
head = ListNode(1, ListNode(2, ListNode(2, ListNode(1))))
print(isPalindrome(head))  # 输出: True

详解

  • 使用快慢指针找到链表中点,翻转前半部分链表,然后逐一比较前后两部分。时间复杂度为 O(n),空间复杂度为 O(1)。

236. 二叉树的最近公共祖先(Lowest Common Ancestor of a Binary Tree)

题目:给定一个二叉树,找到两个指定节点的最近公共祖先。

LeetCode 链接Lowest Common Ancestor of a Binary Tree

Python 实现

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def lowestCommonAncestor(root, p, q):
    if not root or root == p or root == q:
        return root

    left = lowestCommonAncestor(root.left, p, q)
    right = lowestCommonAncestor(root.right, p, q)

    if left and right:
        return root
    return left if left else right

# 使用示例
# 二叉树:       3
#             /   \
#            5     1
#           / \   / \
#          6   2 0   8
#             / \
#            7   4
root = TreeNode(3)
root.left = TreeNode(5)
root.right = TreeNode(1)
p = root.left  # 节点 5
q = root.right  # 节点 1
print(lowestCommonAncestor(root, p, q))  # 输出: 3

详解

  • 使用递归方法,判断左右子树是否包含目标节点。如果左右子树都有节点,说明当前节点就是最近公共祖先。时间复杂度为 O(n),空间复杂度为 O(n)。

238. 除自身以外数组的乘积(Product of Array Except Self)

题目:给定一个数组 nums,返回一个数组,数组的每个元素为除自身以外其他元素的乘积。

LeetCode 链接Product of Array Except Self

Python 实现

def productExceptSelf(nums):
    n = len(nums)
    output = [1] * n
    left = right = 1

    for i in range(n):
        output[i] *= left
        left *= nums[i]

    for i in range(n - 1, -1, -1):
        output[i] *= right
        right *= nums[i]

    return output

# 使用示例
nums = [1, 2, 3, 4]
print(productExceptSelf(nums))  # 输出: [24, 12, 8, 6]

详解

  • 使用两个遍历,分别计算每个位置左边元素的乘积和右边元素的乘积。时间复杂度为 O(n),空间复杂度为 O(1)(除结果数组外)。

279. 完全平方数(Perfect Squares)

题目:给定一个正整数 n,找到若干个完全平方数(如 1, 4, 9, 16 ...)使得它们的和等于 n,你需要让完全平方数的数量最少。

LeetCode 链接Perfect Squares

Python 实现

import math
from collections import deque

def numSquares(n):
    squares = [i**2 for i in range(1, int(math.sqrt(n)) + 1)]
    queue = deque([n])
    level = 0

    while queue:
        level += 1
        for _ in range(len(queue)):
            remainder = queue.popleft()
            for square in squares:
                if remainder == square:
                    return level
                if remainder < square:
                    break
                queue.append(remainder - square)

# 使用示例
n = 12
print(numSquares(n))  # 输出: 3

详解

  • 使用 BFS 逐层递减 n,每次减去一个完全平方数,直到 n 等于某个完全平方数。时间复杂度为 O(n√n),空间复杂度为 O(n)。

300. 最长上升子序列(Longest Increasing Subsequence)

题目:给定一个无序的整数数组,找到其中最长的严格递增子序列的长度。

LeetCode 链接Longest Increasing Subsequence

Python 实现

def lengthOfLIS(nums):
    if not nums:
        return 0

    dp = [1] * len(nums)

    for i in range(1, len(nums)):
        for j in range(i):
            if nums[i] > nums[j]:
                dp[i] = max(dp[i], dp[j] + 1)

    return max(dp)

# 使用示例
nums = [10, 9, 2, 5, 3, 7, 101, 18]
print(lengthOfLIS(nums))  # 输出: 4

详解

  • 动态规划,dp[i] 表示以 nums[i] 结尾的最长上升子序列长度。时间复杂度为 O(n^2),空间复杂度为 O(n)。

322. 零钱兑换(Coin Change)

题目:给定不同面额的硬币 coins 和一个总金额 amount,计算可以凑成该金额的最少硬币数。如果无法凑成,返回 -1。

LeetCode 链接Coin Change

Python 实现

def coinChange(coins, amount):
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0

    for coin in coins:
        for x in range(coin, amount + 1):
            dp[x] = min(dp[x], dp[x - coin] + 1)

    return dp[amount] if dp[amount] != float('inf') else -1

# 使用示例
coins = [1, 2, 5]
amount = 11
print(coinChange(coins, amount))  # 输出: 3

详解

  • 动态规划,dp[i] 表示凑齐金额 i 所需的最少硬币数。时间复杂度为 O(n * amount),空间复杂度为 O(amount)。

继续为你提供更多经典的 LeetCode 题目及其 Python 实现,进一步深入各种算法与数据结构的应用。

406. 根据身高重建队列(Queue Reconstruction by Height)

题目:假设有一群人站成一个队列,每个人由一个整数对 (h, k) 表示,其中 h 是这个人的身高,k 是这个人前面身高大于等于 h 的人数。请根据每个人的身高和 k 值,重新构造队列。

LeetCode 链接Queue Reconstruction by Height

Python 实现

def reconstructQueue(people):
    people.sort(key=lambda x: (-x[0], x[1]))
    queue = []
    for person in people:
        queue.insert(person[1], person)
    return queue

# 使用示例
people = [[7, 0], [4, 4], [7, 1], [5, 0], [6, 1], [5, 2]]
print(reconstructQueue(people))  # 输出: [[5, 0], [7, 0], [5, 2], [6, 1], [4, 4], [7, 1]]

详解

  • 先按身高从高到低排序,若身高相同,则按 k 值升序排序。然后按照 k 值将每个人插入到对应位置。时间复杂度为 O(n^2),空间复杂度为 O(n)。

416. 分割等和子集(Partition Equal Subset Sum)

题目:给定一个只包含正整数的非空数组,是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

LeetCode 链接Partition Equal Subset Sum

Python 实现

def canPartition(nums):
    total_sum = sum(nums)
    if total_sum % 2 != 0:
        return False

    target = total_sum // 2
    dp = [False] * (target + 1)
    dp[0] = True

    for num in nums:
        for i in range(target, num - 1, -1):
            dp[i] = dp[i] or dp[i - num]

    return dp[target]

# 使用示例
nums = [1, 5, 11, 5]
print(canPartition(nums))  # 输出: True

详解

  • 转化为背包问题,目标是找到一个子集,其和等于总和的一半。时间复杂度为 O(n*sum/2),空间复杂度为 O(sum/2)。

494. 目标和(Target Sum)

题目:给定一个整数数组 nums 和一个目标值 S,你可以在数组中每个元素前添加 +-,从而形成一个表达式。找到所有不同的表达式等于 S 的方法数。

LeetCode 链接Target Sum

Python 实现

def findTargetSumWays(nums, S):
    total_sum = sum(nums)
    if total_sum < S or (total_sum + S) % 2 != 0:
        return 0

    target = (total_sum + S) // 2
    dp = [0] * (target + 1)
    dp[0] = 1

    for num in nums:
        for i in range(target, num - 1, -1):
            dp[i] += dp[i - num]

    return dp[target]

# 使用示例
nums = [1, 1, 1, 1, 1]
S = 3
print(findTargetSumWays(nums, S))  # 输出: 5

详解

  • 这是一个转化为子集和问题的动态规划题目。目标是找到一个子集,其和等于 (total_sum + S) / 2。时间复杂度为 O(n*target),空间复杂度为 O(target)。

560. 和为K的子数组(Subarray Sum Equals K)

题目:给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续子数组的个数。

LeetCode 链接Subarray Sum Equals K

Python 实现

def subarraySum(nums, k):
    count = 0
    current_sum = 0
    sum_dict = {0: 1}

    for num in nums:
        current_sum += num
        if current_sum - k in sum_dict:
            count += sum_dict[current_sum - k]
        sum_dict[current_sum] = sum_dict.get(current_sum, 0) + 1

    return count

# 使用示例
nums = [1, 1, 1]
k = 2
print(subarraySum(nums, k))  # 输出: 2

详解

  • 使用哈希表存储前缀和及其出现次数,通过前缀和的差值快速找到满足条件的子数组。时间复杂度为 O(n),空间复杂度为 O(n)。

581. 最短无序连续子数组(Shortest Unsorted Continuous Subarray)

题目:给定一个整数数组,找到一个连续子数组,使得如果对这个子数组进行升序排序,那么整个数组也是升序的。返回你需要排序的最短子数组的长度。

LeetCode 链接Shortest Unsorted Continuous Subarray

Python 实现

def findUnsortedSubarray(nums):
    sorted_nums = sorted(nums)
    start, end = len(nums), 0

    for i in range(len(nums)):
        if nums[i] != sorted_nums[i]:
            start = min(start, i)
            end = max(end, i)

    return end - start + 1 if end >= start else 0

# 使用示例
nums = [2, 6, 4, 8, 10, 9, 15]
print(findUnsortedSubarray(nums))  # 输出: 5

详解

  • 对数组排序,然后比较原数组和排序后的数组,找到第一个和最后一个不同的位置。时间复杂度为 O(n log n),空间复杂度为 O(n)。

647. 回文子串(Palindromic Substrings)

题目:给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

LeetCode 链接Palindromic Substrings

Python 实现

def countSubstrings(s):
    n = len(s)
    dp = [[False] * n for _ in range(n)]
    count = 0

    for i in range(n):
        dp[i][i] = True
        count += 1

    for i in range(n - 1, -1, -1):
        for j in range(i + 1, n):
            if s[i] == s[j]:
                if j - i == 1 or dp[i + 1][j - 1]:
                    dp[i][j] = True
                    count += 1

    return count

# 使用示例
s = "aaa"
print(countSubstrings(s))  # 输出: 6

详解

  • 使用动态规划,dp[i][j] 表示 s[i:j+1] 是否为回文子串。时间复杂度为 O(n^2),空间复杂度为 O(n^2)。

695. 岛屿的最大面积(Max Area of Island)

题目:给定一个包含了一些 0 和 1 的非空二维数组,1 代表陆地,0 代表水域,计算并返回该二维数组中最大的岛屿面积。

LeetCode 链接Max Area of Island

Python 实现

def maxAreaOfIsland(grid):
    def dfs(i, j):
        if i < 0 or i >= len(grid) or j < 0 or j >= len(grid[0]) or grid[i][j] == 0:
            return 0
        grid[i][j] = 0
        return 1 + dfs(i + 1, j) + dfs(i - 1, j) + dfs(i, j + 1) + dfs(i, j - 1)

    max_area = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] == 1:
                max_area = max(max_area, dfs(i, j))

    return max_area

# 使用示例
grid = [
    [0,0,1,0,0,0,0,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,0,0,0],
    [0,1,1,0,1,0,0,0,0,0,0,0,0],
    [0,1,0,0,1,1,0,0,1,0,1,0,0],
    [0,1,0,0,1,1,0,0,1,1,1,0,0],
    [0,0,0,0,0,0,0,0,0,0,1,0,0],
    [0,0,0,0,0,0,0,1,1,1,0,0,0],
    [0,0,0,0,0,0,0,1,1,0,0,0,0]
]
print(maxAreaOfIsland(grid))  # 输出: 6

详解

  • 使用 DFS 遍历岛屿,每次找到一个岛屿时,计算其面积并更新最大面积。时间复杂度为 O(nm),空间复杂度为 O(nm)。

继续为你提供更多 LeetCode 经典题目及其 Python 实现,帮助你深入理解算法和数据结构。

739. 每日温度(Daily Temperatures)

题目:给定一个列表 T,表示每天的温度,返回一个列表 answer,其中 answer[i] 是你需要等待的天数,直到温度超过 T[i] 的天数。如果之后没有更高的温度,answer[i] = 0。

LeetCode 链接Daily Temperatures

Python 实现

def dailyTemperatures(T):
    answer = [0] * len(T)
    stack = []

    for i in range(len(T)):
        while stack and T[i] > T[stack[-1]]:
            prev_day = stack.pop()
            answer[prev_day] = i - prev_day
        stack.append(i)

    return answer

# 使用示例
T = [73, 74, 75, 71, 69, 72, 76, 73]
print(dailyTemperatures(T))  # 输出: [1, 1, 4, 2, 1, 1, 0, 0]

详解

  • 使用单调栈,栈中存储的是温度数组的索引。当遇到比栈顶元素更高的温度时,弹出栈顶并计算等待天数。时间复杂度为 O(n),空间复杂度为 O(n)。

581. 最短无序连续子数组(Shortest Unsorted Continuous Subarray)

题目:给定一个整数数组,找到一个连续子数组,使得如果对这个子数组进行升序排序,那么整个数组也是升序的。返回你需要排序的最短子数组的长度。

LeetCode 链接Shortest Unsorted Continuous Subarray

Python 实现

def findUnsortedSubarray(nums):
    sorted_nums = sorted(nums)
    start, end = len(nums), 0

    for i in range(len(nums)):
        if nums[i] != sorted_nums[i]:
            start = min(start, i)
            end = max(end, i)

    return end - start + 1 if end >= start else 0

# 使用示例
nums = [2, 6, 4, 8, 10, 9, 15]
print(findUnsortedSubarray(nums))  # 输出: 5

详解

  • 对数组进行排序,然后比较原数组和排序后的数组,找到第一个和最后一个不相同的位置。时间复杂度为 O(n log n),空间复杂度为 O(n)。

76. 最小覆盖子串(Minimum Window Substring)

题目:给定两个字符串 st,在 s 中找到最小的包含 t 所有字符的子串,并返回这个子串。如果不存在包含 t 所有字符的子串,则返回空字符串。

LeetCode 链接Minimum Window Substring

Python 实现

from collections import Counter

def minWindow(s, t):
    if not t or not s:
        return ""

    dict_t = Counter(t)
    required = len(dict_t)

    l, r = 0, 0
    formed = 0
    window_counts = {}

    ans = float("inf"), None, None

    while r < len(s):
        char = s[r]
        window_counts[char] = window_counts.get(char, 0) + 1        
        if char in dict_t and window_counts[char] == dict_t[char]:
            formed += 1

        while l <= r and formed == required:
            char = s[l]
            if r - l + 1 < ans[0]:
                ans = (r - l + 1, l, r)

            window_counts[char] -= 1
            if char in dict_t and window_counts[char] < dict_t[char]:
                formed -= 1

            l += 1    
        r += 1

    return "" if ans[0] == float("inf") else s[ans[1]: ans[2] + 1]

# 使用示例
s = "ADOBECODEBANC"
t = "ABC"
print(minWindow(s, t))  # 输出: "BANC"

详解

  • 使用双指针滑动窗口的方法,窗口从左到右扩展,当窗口包含所有需要的字符时,开始收缩窗口以找到最小覆盖。时间复杂度为 O(n),空间复杂度为 O(t + s)。

312. 戳气球(Burst Balloons)

题目:给定 n 个气球,每个气球上都标有一个数字,气球破裂时你可以获得相邻两个未破裂气球的乘积。通过在恰当的顺序戳破气球,最大化你获得的分数。

LeetCode 链接Burst Balloons

Python 实现

def maxCoins(nums):
    nums = [1] + nums + [1]
    n = len(nums)
    dp = [[0] * n for _ in range(n)]

    for length in range(2, n):
        for left in range(n - length):
            right = left + length
            for i in range(left + 1, right):
                dp[left][right] = max(dp[left][right], 
                                      nums[left] * nums[i] * nums[right] + dp[left][i] + dp[i][right])

    return dp[0][n - 1]

# 使用示例
nums = [3, 1, 5, 8]
print(maxCoins(nums))  # 输出: 167

详解

  • 动态规划,dp[i][j] 表示在 nums[i:j+1] 中能够得到的最大分数。时间复杂度为 O(n^3),空间复杂度为 O(n^2)。

128. 最长连续序列(Longest Consecutive Sequence)

题目:给定一个未排序的整数数组,找出最长连续序列的长度。要求算法的时间复杂度为 O(n)。

LeetCode 链接Longest Consecutive Sequence

Python 实现

```python def longestConsecutive(nums): num_set = set(nums) longest_streak = 0

for num in num_set:
    if num - 1 not in num_set:
        current_num = num
        current_streak = 1

        while current_num + 1 in num_set:
            current_num +=