掘金刷题之路 Day 4 | 豆包MarsCode AI刷题

157 阅读10分钟

功能亮点:云端编辑器与智能提示在刷题过程中的应用

在算法学习的道路上,实践是巩固知识、提高技能的关键。然而,传统的刷题方式往往需要在本地环境中编写、调试代码,这不仅耗时,而且可能会因为环境配置问题而影响学习效率。AI 刷题平台的云端编辑器,为我们提供了一个随时随地编写和运行代码的便捷环境。它集成了编译、运行、调试等功能,无需任何本地配置,打开网页即可开始编程。

智能提示是另一个亮点功能。在编写代码的过程中,云端编辑器会根据你的输入实时提供代码补全、语法纠错等提示。这不仅加快了编码速度,还能帮助我们及时发现代码中的潜在错误,培养良好的编程习惯。

刷题实践:石字移动问题

考察:逻辑思维

问题描述:

小 S 正在玩一个关于石子的游戏,给定一些石子,它们位于一维数轴的不同位置,位置由数组 stones 表示。如果某个石子位于最小或最大的一个位置,我们称其为端点石子。

在每一回合,小 S 可以将一个端点石子移动到一个未被占据的位置,使其不再是端点石子。游戏继续进行,直到所有石子的位置变得连续,无法再进行任何移动操作。

你需要帮助小 S 找到可以移动的最大次数。

我的问题,样例无法看懂??

样例1:

输入: stones = [7, 4, 9]

初始状态:

  • 石子位置:4、7、9
  • 已占据位置:4、7、9
  • 空位:5、6、8

目标: 通过移动端点石子,使石子的位置变得连续,计算最大可移动次数。

移动步骤:

第一步:

  • 当前端点石子: 位置 4 和位置 9(最小和最大位置的石子)。
  • 选择移动位置 9 的石子:
    • 可移动到的位置: 位置 5、6、8(未被占据的空位)。
    • 尝试将位置 9 的石子移动到位置 6:
      • 移动后石子位置:4、6、7
      • 新的端点石子:位置 4(最小),位置 7(最大)
      • 移动后的石子(位置 6)不再是端点石子。
      • 第一步成功,移动次数加 1,总移动次数为 1。

第二步:

  • 当前端点石子: 位置 4 和位置 7
  • 选择移动位置 4 的石子:
    • 可移动到的位置: 位置 5(未被占据的空位)。
    • 将位置 4 的石子移动到位置 5:
      • 移动后石子位置:5、6、7
      • 石子位置连续,游戏结束。
      • 第二步成功,移动次数加 1,总移动次数为 2。

最终状态:

  • 石子位置:5、6、7(连续)
  • 总共移动次数:2

结果:

  • 最大可移动次数为 2。

样例2:

输入: stones = [6, 5, 4, 3, 10]

初始状态:

  • 石子位置:3、4、5、6、10
  • 已占据位置:3、4、5、6、10
  • 空位:7、8、9

目标: 通过移动端点石子,使石子的位置变得连续,计算最大可移动次数。

移动步骤:

第一步:

  • 当前端点石子: 位置 3 和位置 10
  • 选择移动位置 10 的石子:
    • 可移动到的位置: 位置 7、8、9(未被占据的空位)。
    • 将位置 10 的石子移动到位置 7:
      • 移动后石子位置:3、4、5、6、7
      • 新的端点石子:位置 3(最小),位置 7(最大)
      • 移动后的石子(位置 7)不再是端点石子。
      • 第一步成功,移动次数加 1,总移动次数为 1。

第二步:

  • 当前端点石子: 位置 3 和位置 7
  • 选择移动位置 3 的石子:
    • 可移动到的位置: 位置 8、9、10(未被占据的空位)。
    • 将位置 3 的石子移动到位置 8:
      • 移动后石子位置:4、5、6、7、8
      • 新的端点石子:位置 4(最小),位置 8(最大)
      • 移动后的石子(位置 8)不再是端点石子。
      • 第二步成功,移动次数加 1,总移动次数为 2。

第三步:

  • 当前端点石子: 位置 4 和位置 8
  • 选择移动位置 4 的石子:
    • 可移动到的位置: 位置 9、10(未被占据的空位)。
    • 将位置 4 的石子移动到位置 9:
      • 移动后石子位置:5、6、7、8、9
      • 新的端点石子:位置 5(最小),位置 9(最大)
      • 移动后的石子(位置 9)不再是端点石子。
      • 第三步成功,移动次数加 1,总移动次数为 3。

最终状态:

  • 石子位置:5、6、7、8、9(连续)
  • 总共移动次数:3

结果:

  • 最大可移动次数为 3。

解释:

  • 通过上述移动步骤,我们成功地将石子排列成连续的位置,且总共进行了 3 次合法的移动。
  • 关键在于每次选择合适的端点石子进行移动,使得移动后的石子不再是端点石子,并且为下一步的移动创造条件。

注意:

  • 在第二步中,我们将位置 3 的石子移动到了位置 8,而不是位置 7,因为位置 7 已经被占据。
  • 在第三步中,我们移动了新的端点石子(位置 4 的石子)到更大的空位,以继续缩小端点之间的距离。

样例3:

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

初始状态:

  • 石子位置:1、2、3、4、5(已经连续)
  • 已占据位置:1、2、3、4、5
  • 空位:无

目标: 判断是否可以移动石子,计算最大可移动次数。

分析:

  • 石子已经连续排列,没有空位可供移动。
  • 端点石子(位置 1 和位置 5 的石子)无法移动:
    • 左侧没有空位(对于位置 1 的石子)。
    • 右侧没有空位(对于位置 5 的石子)。
  • 因此,无法进行任何合法的移动。

结果:

  • 最大可移动次数为 0。

解释:

  • 由于石子已经连续排列,且没有空位,无法进行任何移动操作。
我的问题,游戏结束条件

游戏结束的条件:

  • 石子的位置连续。
  • 没有端点石子可以移动(即,所有端点石子都无法再移动使自己不再是端点石子)

我的思路

  1. 排序石子: 为了方便计算间隙,先将石子的位置进行排序。
  2. 计算总空位数:
    • 计算方法:totalEmpty = stones[n - 1] - stones[0] + 1 - n,其中 n 是石子的数量。
    • 解释:最大位置减去最小位置再加 1(表示位置的总数),减去石子的数量,得到空位的数量。
  1. 计算两端的间隙:

    • 左端间隙(最小位置左侧): leftGap = stones[1] - stones[0] - 1
    • 右端间隙(最大位置右侧): rightGap = stones[n - 1] - stones[n - 2] - 1
  2. 找到最小的端点间隙:

    • minGap = Math.min(leftGap, rightGap)
    • 这个值表示在端点石子可以移动的最小限制,因为当一端的间隙为 0 时,该端的石子无法再移动。
  3. 计算最大可移动次数:

    • maxMoves = totalEmpty - minGap

最终AC代码:

import java.util.*;

public class Main {
    public static int solution(int[] stones) {
        int n = stones.length;
        if(n==1) return 0;
        Arrays.sort(stones);
        int totalEmpty = stones[n - 1] - stones[0] + 1 - n;
        int leftGap = stones[1] - stones[0] - 1;
        int rightGap = stones[n - 1] - stones[n - 2] - 1;
        int minGap = Math.min(leftGap, rightGap);
        int maxMoves = totalEmpty - minGap;
        return maxMoves;
    }

    public static void main(String[] args) {
        System.out.println(solution(new int[]{7, 4, 9}) == 2);
        System.out.println(solution(new int[]{6, 5, 4, 3, 10}) == 3);
        System.out.println(solution(new int[]{1, 2, 3, 4, 5}) == 0);
    }
}

证明思路:

  1. 石子移动的限制条件:

    • 只能移动端点石子(最小或最大位置的石子)。
    • 移动后的石子不能再是端点石子。
    • 移动到的目标位置必须是未被占据的位置。
  2. 目标:

    • 找到最大可能的移动次数,使得最后石子的位置变得连续。
  3. 关键:

    • 总空位数决定了最多可以填补多少个位置。
    • 端点石子两侧的间隙会影响石子的可移动性,特别是当某一侧的间隙为 0 时,那个端点石子无法移动。

步骤一:计算总空位数

    • 总空位数 totalEmpty 计算方法为:最大位置减去最小位置再加 1,减去石子数量,即
      totalEmpty = stones[n - 1] - stones[0] + 1 - n
    • 这表示在石子范围内,未被占据的位置数量。

步骤二:计算两端的间隙

步骤三:确定受限的端点

步骤四:计算最大可移动次数

    • 左端间隙(最小位置右侧的空位):
      leftGap = stones[1] - stones[0] - 1
    • 右端间隙(最大位置左侧的空位):
      rightGap = stones[n - 1] - stones[n - 2] - 1
    • 这些间隙表示端点石子在其一侧可以移动的最大距离。
    • 如果某个端点的间隙为 0,说明该端点石子无法移动,因为它已经被其他石子紧邻着,无法满足移动后不再是端点石子的条件。
    • 最小的端点间隙 minGap 决定了可以影响到最大移动次数的限制因素。
    • 最大可移动次数 maxMoves 计算方法为:
      maxMoves = totalEmpty - minGap
    • 解释:
  • 总空位数表示理论上可以填补的最大位置数。
  • 减去 minGap,因为在间隙为 0 的情况下,无法移动那个端点石子,因此少了一次移动机会。
  1. 为什么可以这样写:

端点石子的移动策略:

  • 每次移动端点石子,使其不再是端点石子,这意味着我们在尽可能地填补内侧的空位。
  • 由于规则限制,我们只能移动到未被占据的位置,且不能成为新的端点石子。

间隙的影响:

  • 当某个端点的间隙为 0 时,该端点石子无法移动,限制了最大移动次数。
  • 因此,需要考虑两端间隙的最小值来调整总的移动次数。

贪心策略的合理性:

  • 我们总是优先移动可以移动的端点石子,填补内部的空位。
  • 这种策略保证了每次移动都是最优的,最终得到最大可能的移动次数。

AI 刷题平台的优势:

  • 实时反馈: 在云端编辑器中运行代码,可以立即看到输出结果,方便验证算法的正确性。
  • 智能提示: 编辑器根据上下文提供代码补全和语法检查,减少了编码过程中的低级错误。
  • 随时随地: 无需安装任何软件,打开浏览器即可开始编程,非常适合碎片化时间的学习。

学习收获:

通过这次实践,我深刻体会到逻辑思维在算法解题中的重要性。对于复杂的问题,理清思路,分步解决,才能找到最优解。

云端编辑器和智能提示功能,提高了我的编码效率,减少了调试时间。同时,AI 刷题平台的便捷性,使我能够更加专注于算法本身的学习与思考。

总结:

算法的学习离不开大量的实践,而一个好的工具能够事半功倍。AI 刷题平台的云端编辑器与智能提示,为我们提供了一个高效的编程环境。在这个平台上,我不仅提高了编程技能,更培养了良好的编码习惯和逻辑思维能力。