题目解析 石子移动问题| 豆包MarsCode AI 刷题

82 阅读2分钟

题目传送门

石子移动问题 - MarsCode

题意简述

小S正在玩一个关于石子的游戏,给定了一些石子,它们位于一维数轴的不同位置。石子的位置用数组 stones 表示。如果某个石子处于最小或最大的一个位置,我们称其为端点石子。在每个回合,小S可以将一颗端点石子移动到一个未占用的位置,使其不再是端点石子。游戏继续,直到石子的位置变得连续,无法再进行任何移动操作。目标是找到可以移动的最大次数。

解题思路

  • 排序石子位置:

  • 首先对石子的位置进行排序,以便于计算端点石子之间的空位。

  • 判断初始连续性:

  • 如果石子已经连续,即 stones[n-1] - stones[0] + 1 == n,则无法进行任何操作,返回0。

3. 计算最大操作次数:

  • 计算两种可能的最大操作次数:

  • 移动最左端石子:将 stones[0] 移动到 stones[1] 之前的空位,计算剩余的空位数。

  • 移动最右端石子:将 stones[n-1] 移动到 stones[n-2] 之后的空位,计算剩余的空位数。

  • 选择上述两种操作中可以进行的最大次数。

4. 公式推导:

  • 如果选择移动 stones[0],最大操作次数为 stones[n-1] - stones[1] + 1 - (n - 1)。

  • 如果选择移动 stones[n-1],最大操作次数为 stones[n-2] - stones[0] + 1 - (n - 1)。

  • 取两者的最大值作为最终结果。

代码实现

import java.util.Arrays;

public class Main {
    public static int solution(int[] stones) {
        Arrays.sort(stones);
        if (stones[stones.length - 1] - stones[0] + 1 == stones.length) return 0;
        return Math.max(stones[stones.length - 2] - stones[0] + 1, stones[stones.length - 1] - stones[1] + 1) - (stones.length - 1);
    }

    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);
    }
}

时间复杂度分析

该算法的时间复杂度为 𝑂(𝑛log⁡𝑛)O(nlogn),主要由于对石子位置进行排序的操作。排序后,计算最大操作次数的步骤是线性的。

用到的算法和数据结构

  • 排序:对石子位置进行排序,以便于计算端点石子之间的空位。

  • 数学推导:通过计算端点石子之间的空位,推导出最大操作次数。

详细分析

在实现过程中,我们首先对石子的位置进行排序,以便于计算端点石子之间的空位。接下来,我们检查石子是否已经连续,如果是,则无法进行任何操作。否则,我们计算两种可能的最大操作次数:移动最左端石子和移动最右端石子。通过比较这两种操作的结果,我们可以确定可以进行的最大操作次数。通过这种方法,我们能够有效地计算出在给定条件下可以进行的最大操作次数。