端点石子移动问题 | 豆包MarsCode AI刷题

134 阅读3分钟

1.端点石子移动问题

问题描述

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

在每个回合,小S可以将一颗端点石子移动到一个未占用的位置,使其不再是端点石子。值得注意的是,如果石子的位置是连续的,则游戏结束,因为没有可以进行的移动操作。

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


测试样例

样例1:

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

样例2:

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

样例3:

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

2.解题思路

小S需要将一维数轴上的石子位置调整成连续的,且每次只能移动端点石子(即位于数轴最小或最大位置的石子)。目标是通过最少的移动次数使石子位置变得连续,或者判断是否已经是连续状态。

解题步骤

  1. 排序石子位置: 由于数组 stones 给出的是无序的石子位置,因此首先对它进行排序,方便后续连续性判断和窗口操作。

  2. 判断是否已连续

    • 排序后,如果首尾石子位置之间的间距恰好等于石子总数减一(即 stones[n-1] - stones[0] + 1 == n),则石子已经连续,不需要任何移动,返回 0。
  3. 滑动窗口找最小移动次数

    • 使用滑动窗口算法遍历石子的排列,找到包含最多石子的连续区间。滑动窗口长度设置为石子总数 n,计算每个窗口内的石子数量并找出窗口外的空位数量(即非连续部分)。
    • 滑动窗口遍历过程中,j 为窗口右边界,i 为左边界。在每个位置 i 处,将窗口扩大到 i + n 的位置。窗口内石子数量与 n 的差值即为移动次数。
  4. 特殊情况处理

    • 如果窗口内只差一个空位(即当前窗口内石子间距刚好差 1 的连续情况),需要特殊处理,因为此种情况下可能要多移一步。

3.代码实现

import java.util.Arrays;

public class Main {
    public static int solution(int[] stones) {
        int n = stones.length;
        Arrays.sort(stones);

        // 检查是否已经是连续的
        if (stones[n - 1] - stones[0] + 1 == n) return 0;

        // 滑动窗口找最小移动次数
        int minMoves = n; // 初始化为一个大值
        int j = 0;
        for (int i = 0; i < n; i++) {
            while (j < n && stones[j] < stones[i] + n) j++;
            int currentMoves = n - (j - i);
            if (currentMoves == 1 && stones[j - 1] - stones[i] + 1 == n - 1) currentMoves++; // 特殊情况
            minMoves = Math.min(minMoves, currentMoves);
        }

        return minMoves;
    }

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

这段代码的核心目标是找出石子位置最少移动次数,以使所有石子在数轴上连续。代码首先对石子位置数组 stones 进行排序,以便按位置顺序处理。接着通过滑动窗口的方法检查石子之间的空隙数量,窗口长度为石子总数 n。滑动窗口遍历每个可能的连续子区间,以确定包含最大石子数的区间,这样可以找出需要移动的最少石子数量。最终返回最小移动次数,特例是在窗口内只差一个位置时的情况,这种情况下可能需额外一步调整。

4.复杂度分析

排序 stones 的时间复杂度为 O(nlog⁡n)O(n \log n)O(nlogn),滑动窗口操作的时间复杂度为 O(n)O(n)O(n),因此总时间复杂度为 O(nlog⁡n)O(n \log n)O(nlogn)。