AI刷题记录 | 石子移动问题2

69 阅读2分钟

这个博客不是《石子移动问题》的解答,《石子移动问题》里求的是最大值,这里探讨一下最小值问题。AI刷题记录 | 石子移动问题先贴一下此题通过的代码(JAVA版本) 此题直接使用右侧AI提供的思路来写是无法通过的,正 - 掘金 (juejin.cn)这个博客记录了最大值的解法。

贴一下求解最小值问题的代码(JAVA版本)

题目参考力扣1040

class Solution {
    public int[] numMovesStonesII(int[] stones) {
        //最大石子的移动数
        Arrays.sort(stones);
        
        int max = 0;
        //计算有多少个空位
        int n =  stones.length;
        int spand = stones[n-1] - stones[0] + 1;
        int remain = spand - n;
        max = Math.max(remain - (stones[1]-stones[0]-1),remain-(stones[n-1]-stones[n-2]-1));


        //最小的石子移动数
        int start = 0,end = 0;
        int cnt = 1;
        int min = max;
        while(end<n){
            if(stones[end] - stones[start] + 1<n){
                end++;
                cnt++;             
            }else if(stones[end] - stones[start] + 1==n){
                if(cnt == n-1){
                    min = 1;
                }else{
                    min = Math.min(min,n-cnt);
                }
                end++;
                start++;
            }else{

                if(cnt == n-1){
                   min = 2;
                }else{
                    min = Math.min(min,n-cnt+1);
                }
                start++;
                cnt--;
            }

        }
        return new int[]{min,max};
    }
}

思路

这道题的核心思想是将所有石子移动到一个长度为 n 的窗口内,使得窗口中的石子最终连续排列。为了最小化移动次数,我们首先分析各种情况,并通过合理选择窗口和移动策略来确定最少的操作数。

关键分析:

  1. 窗口中的连续石子:我们需要找到一个长度为 n 的窗口,其中尽可能多的石子已经处于连续排列的状态。如果窗口中有 n-1 个石子已经连续,且剩余的一个石子与窗口中的某个石子之间的空位数为 1,则只需一次操作即可使所有石子连续。否则,若空位数大于 1,则需要两次操作:第一步移动一个石子填补空位,第二步将剩余的石子移动到连续区间中。
  2. 窗口选择:如果当前窗口中没有足够多的石子,或连续的石子不足,我们选择石子最多的窗口作为目标窗口。假设窗口中已有k 个石子,则需要 n-k 次操作才能将所有空位填满。

注意

此题需要注意当窗口内的连续石子达到n-1的情况。由于题目限制端点石子操作后必须不能再为端点石子,这样可能会出现端点石子无法一步到位,需要借助中间石子两步完成的情况。第一步,搭建一个中间石子,第二步再把端点石子归位。但是,如果窗口外面剩余的石子大于等于两个就不会有这种情况,这时候我们可以随意选择则窗口外的一个石子去充当中间石子,这一步并不会增加石子的移动次数。