题目描述
题解思路
数据范围没有截图到,这里的数据范围为0-20000
题目的内容还是很好理解的,就是给你一个数组,你可以将数组内容向左推移若干次,而我们定义如果数组当前位置的值小于其索引即可得分,求使得得分最大的那个推移次数。
首先,单从模拟的思路来说,我们很容易想到的一点是我们直接暴力来枚举所以的n的次数,然后再求每个次数的分数,但是可惜的是,这个算法的时间复杂度为O(n2),因为最高的数据可以到20000,显然会TLE
由于这个数据范围,我们就得重新来审视题目了,很明显的一点是,对于任意的一个数值,他都有自己的独有的得分区域,例如在长度为7(索引范围为0-6)的数组中,有一个值为5,那么如果我们要得到这个值的点数,则一定要让这个值位于索引[5,6]间,那么[5-6]就是这个值的得分区域,而[0,4]就不是他的得分区域,那么,我们只需要求出值在第几次移动时进入得分区域,那么这个推动的范围就是得分范围。
那么此时,我们的任务就变成了找到最大的重合数,找到重合最多次数的推动范围,我们就可以得到最高的分数,而进入这个范围的那个值则为我们所需要的k值。
而这又该怎么解决呢?前缀和!!!
前缀和算是算法中常用的一种方法了,之后我也会写一篇博客来专门梳理一下(给自己梳理一下hhhh)
代码
class Solution {
public int bestRotation(int[] nums) {
int k = nums.length;
int[] turns = new int[k+5];
for(int i = 0;i<k;i++)
{
int num = nums[i];
if(num>i)//判断值大于初始位置(即初始不得分)
{
turns[i+1]++;
turns[k+1-(num-i)]--;
}
else//初始得分情况
{
turns[0]++;
turns[i-num+1]--;
turns[i+1]++;
}
}
int zhi = 0,mzhi = 0,ansk = 0;
for(int i = 0;i<k;i++)//前缀和方法
{
zhi += turns[i];
if(zhi > mzhi)
{
mzhi = zhi;
ansk = i;
}
}
return ansk;
}
}
结语
如果有想一起每天互相监督刷题的小伙伴可以加上微信,咱们一起加油呀!也可以一起讨论讨论题目