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

91 阅读2分钟

问题描述

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

在每个回合,小S可以将一颗端点石子移动到一个未占用的位置,使其不再是端点石子。游戏继续,直到石子的位置变得连续,无法再进行任何移动操作。

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


测试样例

样例1:

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

样例2:

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

样例3:

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

问题分析

  1. 理解端点石子:端点石子是指位于数组 stones 中最小或最大位置的石子。
  2. 移动规则:每次可以将一个端点石子移动到一个未占用的位置,使其不再是端点石子。
  3. 目标:计算可以进行的最大移动次数,直到石子的位置变得连续。

解题思路

  1. 排序:首先对 stones 数组进行排序,这样可以更容易地找到端点石子。
  2. 计算空位:计算排序后的 stones 数组中,相邻石子之间的空位数。
  3. 移动次数:最大移动次数等于空位数减去已经存在的石子数。
  4. 两端特殊处理:对于最后求出的最大移动次数ans,仍需对其做处理,让其减去两端石子相邻空格数量中的较小值,此时方为最终答案。

下面是我写的代码(C++)

#include<bits/stdc++.h>
using namespace std;

int solution(vector<int>& stones) {
    // write code here
    sort(stones.begin() , stones.end());
    int n = stones.size();
    int ans = 0;
    if(n <= 2)
    return 0;
    for(int i = 0; i < n - 1; i++)
    {
        ans += stones[i + 1] - stones[i] - 1;
    }
    int a = stones[1] - stones[0] - 1;
    int b = stones[n-1] - stones[n-2] - 1;
    int s = min(a , b);
    ans -= s;
    return ans;
}

int main() {
    vector<int>p;
    int t;
    while(cin >> t)
    {
        p.push_back(t);
    }
    cout << solution(p);
    return 0;
}

关键步骤分析

  1. 排序:使用 sort 函数对 stones 数组进行排序。
  2. 计算空位:遍历排序后的 stones 数组,计算相邻石子之间的空位数,并累加到 ans 中。
  3. 减去两端数:减去两端石子相邻空位数量中的较小值。
  4. 返回结果:返回 ans 作为最大移动次数。

注意特殊情况

当n <= 2时,不必对数据进行处理,直接return 0即可。

写在最后

这道题用到了一些数学思维,对数学比较敏感的同学写这道题会较为轻松,这道题也可以帮助我们训练数学思维。