LeetCode 1033 移动石子直到连续 和 1040. 移动石子直到连续 II

题1033
三枚石子放置在数轴上,位置分别为 a,b,c。

每一回合,我们假设这三枚石子当前分别位于位置 x, y, z 且 x < y < z。从位置 x 或者是位置 z拿起一枚石子,并将该石子移动到某一整数位置 k 处,其中 x < k < z 且 k != y。

当你无法进行任何移动时,即,这些石子的位置连续时,游戏结束。

要使游戏结束,你可以执行的最小和最大移动次数分别是多少? 以长度为 2 的数组形式返回答案:answer = [minimum_moves, maximum_moves]

当石子个数只有三个时,且可以把首尾石子向中间任意移动时,可以考虑各种情况下的排列状态来解决这个问题。
求最大移动步数时,只要左右两个石子一步一步向之间移动即可。
res[1]=arr[2]-arr[1]-1+arr[1]-arr[0]-1;
求最小移动步数时,考虑不同的情况
当有两个石子紧挨着的时候,另一个石子只要一步即可。
当有两个石子相隔一个时,将另一个移动到中间即可。
当任意两个石子之间空格大于1时,只需要移动一步使两个石子相隔一个,再将另一个移动到空格,总共移动两步。

  public int[] numMovesStones(int a, int b, int c) {
        int[] arr={a,b,c};
        Arrays.sort(arr);
        int[] res=new int[2];
        if(arr[1]-arr[0]==1||arr[2]-arr[1]==1){
            res[0]=arr[1]-arr[0]>1||arr[2]-arr[1]>1?1:0;
        }else  if(arr[1]-arr[0]==2||arr[2]-arr[1]==2){
            res[0]=1;
        }else{
            res[0]=2;
        }
        res[1]=arr[2]-arr[1]-1+arr[1]-arr[0]-1;
        return res;
    }

题目1040 在一个长度无限的数轴上,第 i 颗石子的位置为 stones[i]。如果一颗石子的位置最小/最大,那么该石子被称作端点石子。
每个回合,你可以将一颗端点石子拿起并移动到一个未占用的位置,使得该石子不再是一颗端点石子。 值得注意的是,如果石子像 stones =
[1,2,5] 这样,你将无法移动位于位置 5 的端点石子,因为无论将它移动到任何位置(例如 0 或 3),该石子都仍然会是端点石子。
当你无法进行任何移动时,即,这些石子的位置连续时,游戏结束。 要使游戏结束,你可以执行的最小和最大移动次数分别是多少? 以长度为 2
的数组形式返回答案:answer = [minimum_moves, maximum_moves] 。

这个题目主要参考了LeetCode上的题解,思考起来还是稍微复杂一点的,主要思路是在数轴上找一个长度为n的区间,这个区间上的所有空格都可以被区间外的石子填满,空格数量最少时,移动步数最少。
而要步数最多,只要在初始的总区间上,计算空格数量,除了第一步在移动之后会造成一段空格的消失,其他的空格都可以一步一步填满,也就是加到总步数中。

    public int[] numMovesStonesII(int[] stones) {
        Arrays.sort(stones);
        int n=stones.length;
        int mx=stones[n-1]-stones[0]+1-n;//首位之间的空格数量
        mx-=Math.min(stones[n-1]-stones[n-2] - 1, stones[1]-stones[0] -1);//移动首尾某个石子后最大的步数
        int mi = mx;
        int i = 0;
        int j = 0;
        for(i = 0; i < n; ++i)
        {
            while(j + 1 < n && stones[j + 1] - stones[i] + 1 <= n)//以i为起点,找一个长度为n的分段
                ++j;  //j+1是最后一个
            int cost = n - (j - i + 1);//cost表示中间这段有几个空格,j-i+1表示的石子个数
            if(j - i + 1 == n - 1 && stones[j] - stones[i] + 1 == n - 1)
                //如果出现了长度为n的分段中有n-1个石子,且是紧挨着的,需要2步
                cost = 2;
            mi = Math.min(mi, cost);

        }
        return new int[]{mi,mx};
    }

参考:LeetCode题解

发布了47 篇原创文章 · 获赞 1 · 访问量 1610

猜你喜欢

转载自blog.csdn.net/chinamen1/article/details/102779038