题目解析
题目描述:
小S正在玩一个关于石子的游戏,给定了一些石子,它们位于一维数轴的不同位置,位置用数组 stones 表示。如果某个石子处于最小或最大的一个位置,我们称其为端点石子。
在每个回合,小S可以将一颗端点石子移动到一个未占用的位置,使其不再是端点石子。游戏继续,直到石子的位置变得连续,无法再进行任何移动操作。
你需要帮助小S找到可以移动的最大次数。
思维详解:
现在题目给出一个长度无限的数轴一个长度为 n 数组 stones,表示 n 颗石子在数轴上的不同位置,其中第 i,0≤i<n 颗石子的位置在 stones[i] 上,其中若一颗石子的位置最小/最大,则该石子被称为端点石子。现在我们每次需要将一颗端点石子移动到一个未占用的位置上,使得其不再是一颗端点石子,若无法进行操作则停止。我们需要返回从初始状况开始可以进行操作的最大操作次数。
我们记这些石子的长度为两端点石子之间的距离差,则通过题意可以得到每次移动石子的长度严格递减,并由于石子的总个数不变,所以石子间的空位越来越少。通过移动最终让所有石子连续,实质上就是让石子间的空位为 0。现在我们开始考虑如何求解最大操作数和最小操作数,为了方便描述,我们不妨对数组 stones 中的石子按照位置大小升序排序,即满足
stones[0]<stones[1]<⋯<stones[n−1]
首先若初始时全部石子已经连续,即空位数 stones[n−1]−stones[0]+1−n 为 0,则此时不能进行操作,最大操作数和最小操作数都为 0,否则:
第一次我们只能选择 stones[0] 或者 stones[n−1] 进行移动。因为移动后不能继续成为端点石子,所以若移动 stones[0],则 stones[1] 到 stones[0] 之间的空位将会被丢弃,若移动 stones[n−1],则 stones[n−1] 到 stones[n−2] 之间的空位将会被丢弃,如果我们每次移动都将端点石子移到其最近的空位,则第一次移动后,若移动 stones[0],则此时最左端的两个石子一定保证相邻,此时我们在之后的操作中都将最左端的石子移动到与之最近的空位中,直至不能进行操作,这样剩下的空位都不会被丢弃。若移动 stones[n−1],同理此时最右端的两个石子一定保证相邻,此时我们在之后的操作中都将最右端的石子移动到与之最近的空位中,直至不能进行操作,这样剩下的空位同样都不会被丢弃。由于每次操作必定会少一个空位,所以在第一次移动后,上述的两者操作都是最优操作,又因为最初的总空位是固定的,所以若我们第一次选择移动 stones[0],则可以操作的总次数为
stones[n−1]−stones[1]+1−(n−1)(1)
若我们第一次选择移动 stones[n−1],则可以操作的总次数为
stones[n−2]−stones[0]+1−(n−1)(2)
那么两者中的较大值即为最大的操作数。
代码详解:
import java.util.Arrays;
public class Main {
public static int solution(int[] stones) {
// write code here
int max=0;
int target=0;
if(stones.length==1||stones.length==0)
{
return 0;
}
Arrays.sort(stones);
for(int i=1;i<stones.length;i++)
{
max=(stones[i]-stones[i-1]-1)>max?(stones[i]-stones[i-1]-1):max;
}
if(max==0)
{
return 0;
}
target=Math.max(stones[stones.length - 2] - stones[0] + 1, stones[stones.length - 1] - stones[1] + 1) - (stones.length - 1);
return target;
}
public static void main(String[] args) {
System.out.println(solution(new int[]{7, 4, 9}) == 2);
System.out.println(solution(new int[]{6, 5, 4, 3, 10}) == 3);
System.out.println(solution(new int[]{1, 2, 3, 4, 5}) == 0);
}
}
知识总结
这道题考递推思维,多想多练!
学习计划
豆包MarsCode AI在我的刷题过程中给了我很大的帮助,千里之行始于足下,解题第一步就是读懂题,AI助手很好的为我明晰了题目要义。并且在解题过程中,AI助手也可以为我实时分析代码逻辑与漏洞,以防编程过程中的逻辑模糊现象,大大提升了解题效率。
工具运用
这里建议其他码友在题意不明时询问豆包AI,让其进行读题,明确题意。代码编程卡顿时借助AI对现有代码进行逻辑分析,获取接下来的解题思路,可有效提升效率,但要注意AI不是万能的,不能全部照抄,要融入自己的理解,才能获得最精确的题解。同时,如果发现代码于某些样例存在问题,可询问豆包AI当前代码是否存在边界问题没有考虑到。