返回

数组的移动——三道LeetCode刷题指南,各显其能

前端

克服数组移动难题:探索 453、665 和 283

在编程世界中,数组移动问题是常见且具有挑战性的难题。它们要求你操纵数组中的元素,执行各种操作,例如移动、删除和替换。解决这些问题不仅可以磨练你的算法技能,还可以让你更深入地了解数组在编程中的作用。本文将深入探讨三个经典的数组移动问题:453、665 和 283,为你提供分步解决方案和代码示例,帮助你巩固基础并提升编程能力。

453. 最小操作次数使数组元素相等

问题
给定一个整数数组 nums,找出将数组中的所有元素变为相同的最少操作次数。每个操作只能将数组中的一个元素增加 1。

解决方案:

方法 1:
一个直接的方法是创建数组 nums 的副本,并在副本上进行操作。这种方法时间复杂度为 O(n),其中 n 是数组的长度,空间复杂度也为 O(n)。

方法 2:
一种更有效的方法是在原数组上进行操作。我们可以维护一个列表,记录数组中非零元素的位置。然后,我们可以遍历数组,将非零元素移动到数组的前面。这种方法的时间复杂度为 O(n),空间复杂度为 O(1)。

Python 代码:

def minMoves(nums):
    # 记录非零元素的位置
    non_zero_indices = []

    # 遍历数组,记录非零元素位置
    for i, num in enumerate(nums):
        if num != 0:
            non_zero_indices.append(i)

    # 将非零元素移动到数组前面
    for i in range(len(non_zero_indices)):
        nums[i] = nums[non_zero_indices[i]]

    # 将剩余元素置为 0
    for i in range(len(non_zero_indices), len(nums)):
        nums[i] = 0

    # 返回移动次数
    return len(non_zero_indices)

665. 非递减数列

问题:
给定一个长度为 n 的整数数组 nums,判断是否可以通过对数组中一个元素进行一次递增操作,使其成为一个非递减数列。

解决方案:

方法 1:
我们可以遍历数组,如果遇到一个元素小于前一个元素,则可以尝试对其进行递增操作。如果递增操作后数组仍是递减的,则返回 false。否则,返回 true。

方法 2:
我们可以使用栈来解决这个问题。遍历数组,如果遇到一个元素小于前一个元素,则将其与前一个元素一起压入栈中。然后,检查栈中元素是否满足非递减条件。如果满足,则弹出栈中元素,继续遍历数组。否则,返回 false。

Python 代码:

def checkPossibility(nums):
    # 创建栈
    stack = []

    # 遍历数组
    for i in range(1, len(nums)):
        # 如果遇到一个元素小于前一个元素
        if nums[i] < nums[i - 1]:
            # 如果栈不为空,检查栈中元素是否满足非递减条件
            if stack:
                # 如果栈顶元素小于前一个元素,返回 false
                if stack[-1] > nums[i - 1]:
                    return False
                # 如果栈顶元素大于前一个元素,弹出栈顶元素
                else:
                    stack.pop()
            # 将该元素和前一个元素都压入栈中
            stack.append(nums[i - 1])
            stack.append(nums[i])

    # 返回 true
    return True

283. 移动零

问题:
给定一个整数数组 nums,将数组中的所有 0 移动到数组末尾,同时保持非零元素的相对顺序。

解决方案:

方法 1:
我们可以遍历数组,遇到 0 就将其移到数组末尾。这种方法时间复杂度为 O(n^2),其中 n 是数组的长度。

方法 2:
我们可以使用两个指针,一个指针指向第一个 0,另一个指针指向第一个非零元素。当两个指针相遇时,交换两个元素。这种方法时间复杂度为 O(n),空间复杂度为 O(1)。

Python 代码:

def moveZeroes(nums):
    # 指向第一个 0 的指针
    zero_ptr = 0

    # 遍历数组
    for i in range(len(nums)):
        # 如果遇到一个非零元素
        if nums[i] != 0:
            # 交换两个元素
            nums[zero_ptr], nums[i] = nums[i], nums[zero_ptr]
            # 移动 zero_ptr
            zero_ptr += 1

结论

解决数组移动问题可以让你深入了解数组的处理以及算法在编程中的作用。通过使用巧妙的算法和数据结构,我们可以高效地操作数组,满足各种问题要求。本文介绍的 453、665 和 283 只是众多数组移动问题中的几个,掌握这些问题可以让你在解决其他类似问题时得心应手。

常见问题解答

  1. 什么是数组移动问题?
    数组移动问题是一类编程问题,要求你对数组中的元素进行各种操作,例如移动、删除和替换。

  2. 为什么解决数组移动问题很重要?
    解决数组移动问题可以磨练你的算法技能,让你更深入地了解数组在编程中的作用。

  3. 本文中介绍的三种数组移动问题有什么不同?
    453. 最小操作次数使数组元素相等:求将数组中所有元素变为相同的最少操作次数。
    665. 非递减数列:判断是否可以通过对数组中一个元素进行一次递增操作,使其成为一个非递减数列。
    283. 移动零:将数组中的所有 0 移动到数组末尾,同时保持非零元素的相对顺序。

  4. 解决数组移动问题时应该使用什么数据结构?
    具体使用什么数据结构取决于问题要求。例如,栈可以用于检查非递减条件,而双指针可以用于移动元素。

  5. 如何提高解决数组移动问题的技能?
    练习是提高解决数组移动问题的技能的关键。尝试解决不同的问题,并从他人那里学习不同的方法。