问题描述
小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
问题分析
- 理解端点石子:端点石子是指位于数组
stones中最小或最大位置的石子。 - 移动规则:每次可以将一个端点石子移动到一个未占用的位置,使其不再是端点石子。
- 目标:计算可以进行的最大移动次数,直到石子的位置变得连续。
解题思路
- 排序:首先对
stones数组进行排序,这样可以更容易地找到端点石子。 - 计算空位:计算排序后的
stones数组中,相邻石子之间的空位数。 - 移动次数:最大移动次数等于空位数减去已经存在的石子数。
- 两端特殊处理:对于最后求出的最大移动次数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;
}
关键步骤分析
- 排序:使用
sort函数对stones数组进行排序。 - 计算空位:遍历排序后的
stones数组,计算相邻石子之间的空位数,并累加到ans中。 - 减去两端数:减去两端石子相邻空位数量中的较小值。
- 返回结果:返回
ans作为最大移动次数。
注意特殊情况
当n <= 2时,不必对数据进行处理,直接return 0即可。
写在最后
这道题用到了一些数学思维,对数学比较敏感的同学写这道题会较为轻松,这道题也可以帮助我们训练数学思维。