返回

剑指 Offer(专项突击版)第11 | 12 题详解与综合剖析

前端

前言

随着前端开发对算法和数据结构要求的提高,在求职过程中遇到算法题的可能性也越来越大。为了帮助大家做好准备,本文将带领大家详细解析《剑指 Offer(专项突击版)》中的第 11 和第 12 题。

题目背景和要求

第 11 题:旋转数组的最小数字

给定一个旋转排序数组,在该数组中,前一部分的元素都大于后一部分的元素。请找出该数组中的最小元素。

示例:

输入:nums = [3, 4, 5, 1, 2]
输出:1

第 12 题:矩阵中的路径

在一个由 '0' 和 '1' 组成的矩阵中,找出从左上角到右下角的路径,使得路径上的所有数字都是 '1'。

示例:

输入:board = [
  ['1', '0', '1', '1', '1'],
  ['1', '0', '1', '1', '1'],
  ['1', '1', '1', '1', '1'],
  ['1', '1', '1', '1', '1'],
  ['1', '1', '1', '1', '1']
]
输出:true

解决思路

对于第 11 题,我们可以使用二分查找法来找到旋转数组中的最小元素。具体步骤如下:

  1. 初始化两个指针,分别指向数组的首元素和尾元素。
  2. 计算数组的中点指针。
  3. 如果中点指针指向的元素大于尾元素指针指向的元素,则说明最小元素在数组的后半部分。将首元素指针移动到中点指针的下一位置。
  4. 如果中点指针指向的元素小于尾元素指针指向的元素,则说明最小元素在数组的前半部分。将尾元素指针移动到中点指针的前一位置。
  5. 重复步骤 2-4,直到首元素指针和尾元素指针相遇。此时,相遇的元素即为最小元素。

对于第 12 题,我们可以使用回溯法来找出从左上角到右下角的路径。具体步骤如下:

  1. 初始化一个二维布尔数组,记录每个位置是否已经访问过。
  2. 从左上角位置开始,依次访问其下方的位置和右边的位置。
  3. 如果当前位置是右下角位置,则说明已经找到一条路径,返回 true。
  4. 如果当前位置的下方位置和右边的位置都没有被访问过,则分别对这两个位置进行递归调用。
  5. 如果当前位置的下方位置和右边的位置都被访问过了,则返回 false。
  6. 如果所有的位置都已被访问过,则说明没有路径,返回 false。

具体实现

def find_min(nums):
  """
  Finds the minimum element in a rotated sorted array.

  Args:
    nums: A list of integers representing a rotated sorted array.

  Returns:
    The minimum element in the array.
  """

  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]


def has_path(board, i, j):
  """
  Checks if there is a path from the given position to the right bottom corner of the board.

  Args:
    board: A 2D list of characters representing the board.
    i: The row index of the current position.
    j: The column index of the current position.

  Returns:
    True if there is a path, False otherwise.
  """

  if i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or board[i][j] == '0':
    return False

  if i == len(board) - 1 and j == len(board[0]) - 1:
    return True

  visited[i][j] = True

  # Check the position below the current position.
  if has_path(board, i + 1, j):
    return True

  # Check the position to the right of the current position.
  if has_path(board, i, j + 1):
    return True

  visited[i][j] = False

  return False


if __name__ == "__main__":
  nums = [3, 4, 5, 1, 2]
  print(find_min(nums))  # Output: 1

  board = [
    ['1', '0', '1', '1', '1'],
    ['1', '0', '1', '1', '1'],
    ['1', '1', '1', '1', '1'],
    ['1', '1', '1', '1', '1'],
    ['1', '1', '1', '1', '1']
  ]
  print(has_path(board, 0, 0))  # Output: True

总结

通过对《剑指 Offer(专项突击版)》第 11 和第 12 题的深入解析,我们了解了如何使用二分查找法和回溯法来解决这些问题。这些算法在实际开发中也有广泛的应用,希望大家能够举一反三,将其应用到自己的项目中去。