> 文章列表 > 【每日一题Day170】LC1040移动石子直到连续 II | 双指针 贪心 数学

【每日一题Day170】LC1040移动石子直到连续 II | 双指针 贪心 数学

【每日一题Day170】LC1040移动石子直到连续 II | 双指针 贪心 数学

移动石子直到连续 II【LC1040】

在一个长度 无限 的数轴上,第 i 颗石子的位置为 stones[i]。如果一颗石子的位置最小/最大,那么该石子被称作 端点石子

每个回合,你可以将一颗端点石子拿起并移动到一个未占用的位置,使得该石子不再是一颗端点石子。

值得注意的是,如果石子像 stones = [1,2,5] 这样,你将 无法 移动位于位置 5 的端点石子,因为无论将它移动到任何位置(例如 0 或 3),该石子都仍然会是端点石子。

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

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

这几天一直在干活 然后昨天下午做题一直被打断 最后我都以为自己已经发好题解了 结果并没有发…

  • 思路

    • 首先,明确每次移动时只能移动端点,并且端点移动后不能还是端点,即移动后石子的左侧和右侧必须有其他石子。每次移动后两边端点的距离较小

    • 什么时候无法移动?

      所有石子之间没有空位,都位于连续的n个位置

    • 如何获得最大移动次数?

      每次移动,都让移动的距离尽可能小【贪心】,那么移动次数就能达到最大。

      那么第一次移动存在两种移动方式

      • 移动stones[0]stones[1]+1
      • 移动stones[n-1]stones[n-2]-1

      而我们之后的每次移动都可以使移动距离为1,从而获得最大的移动次数,移动的次数取决于第一次移动后新端点之间的空位,即

      • s[n−1]−s[1]−1−(n−3)=s[n−1]−s[1]−n+2s[n-1]-s[1]-1-(n-3)=s[n-1]-s[1]-n+2s[n1]s[1]1(n3)=s[n1]s[1]n+2
      • s[n−2]−s[0]−1−(n−3)=s[n−2]−s[0]−n+2s[n-2]-s[0]-1-(n-3)=s[n-2]-s[0]-n+2s[n2]s[0]1(n3)=s[n2]s[0]n+2

      因此,最大移动次数为
      max(s[n−1]−s[1]−n+2,s[n−2]−s[0]−n+2)max(s[n-1]-s[1]-n+2,s[n-2]-s[0]-n+2) max(s[n1]s[1]n+2,s[n2]s[0]n+2)

    • 如何获得最小移动次数?

      由于所有端点可以移动至可以中间任意的空位,那么我们应该尽可能将石子移动至最合适的问题。

      那么我们可以枚举长度为nnn的滑动窗口,计算其中没有石子的位置的个数,取最小值返回。

      但此时存在特殊情况,即移动后石子仍为端点的情况【每日一题Day170】LC1040移动石子直到连续 II | 双指针 贪心 数学

      于是,我们需要判断,s[0]至s[n−2]s[0]至s[n-2]s[0]s[n2]s[1]至s[n−1]s[1]至s[n-1]s[1]s[n1]之间是否有空位,如果没有空位,那么答案为2;还需比较与最大移动次数的关系,如果最小移动次数应小于最大移动次数

      • 滑动窗口
  • 实现

    class Solution {public int[] numMovesStonesII(int[] s) {Arrays.sort(s);int n = s.length;int e1 = s[n - 2] - s[0] - n + 2;int e2 = s[n - 1] - s[1] - n + 2; // 计算空位int maxMove = Math.max(e1, e2);if (e1 == 0 || e2 == 0) // 特殊情况:没有空位return new int[]{Math.min(2, maxMove), maxMove};int maxCnt = 0, left = 0;for (int right = 0; right < n; ++right) { // 滑动窗口:枚举右端点所在石子while (s[right] - s[left] + 1 > n) // 窗口长度大于 n++left; // 缩小窗口长度maxCnt = Math.max(maxCnt, right - left + 1); // 维护窗口内的最大石子数}return new int[]{n - maxCnt, maxMove};}
    }作者:灵茶山艾府
    链接:https://leetcode.cn/problems/moving-stones-until-consecutive-ii/solutions/2212638/tu-jie-xia-tiao-qi-pythonjavacgo-by-endl-r1eb/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    
    • 复杂度
      • 时间复杂度:O(nlogn)O(nlogn)O(nlogn)
      • 空间复杂度:O(1)O(1)O(1)