很久没有写代码了,感觉很明显的脑子转不过来了,题意不难理解,但是需要比较细心的写代码,记录一下吧~~
1.题目
给定一个长度为 n 的非负整数环形数组 a1,a2,…,an
由于环形数组首尾相连,因此 an的下一位元素是 a1
有一个指针,指向该数组中的元素。初始时,该指针指向 a1
接下来执行以下循环操作(由伪代码表示):
while(指针指向的元素不等于 0)
{
令当前数组中所有大于 0 的元素减 1,并令指针指向下一位元素;
}
请你输出循环操作结束后,该指针指向的元素的下标。
输入格式
第一行包含整数 n
第二行包含 n个整数 a1,a2,…,an
输出格式
一个整数,表示指针最终指向的元素的下标。
2.大致思路
1.首先可以肯定的是,绝对不可以用模拟(数值过大时,例如1e9,绝对会超时间复杂度)
2.因此可以有以下思路:
(1)对于每一个下标为i的指针(指针的下标从1-n)有其数值d[i],在第一次指向i时,已经有i-1次-1,就是说在指向时d[i]=d[i]-(i-1),判断此时如果d[i]-(i-1)<=0,则最终指向的元素的下标为i,否则,我们对之后的情况继续模拟。
(2)在第一次指向i时(d[i]>0),在这个while循环(题目中给出的伪代码)中d[i]-1,假设之后的指针没有符合跳出while的情况,则在第二次到达指针i前,共有n次-1,就是说第二次到达指针i时d[i]=d[i]-(i-1)-n,由此可以类推,第k次到达指针i时d[i]=d[i]-(i-1)-(k-1)*n,如果此时d[i]<=0,则说明i为最终指向的元素下标
(3)但是,在这个过程中,我们如何保证i是第一个符合条件的元素呢?不难发现,我们只需要按照1-n顺序进行遍历即可,然后比较代码中的a[i](就是第几次可以跳出循环,a[i]越小就可以越早跳出去了~)
然后就开始快乐的写代码了~~
AC代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5 + 50;
int n,d[N],a[N];
int main() {
cin >> n;
int res = 0;
int cnt = 1e9;
for (int i = 0; i < n; i++) {
cin >> d[i];
}//0,n-1 1,n-1
for (int i = 0; i < n; i++) {
d[i] -= i;
a[i]++;
if (d[i] <= 0) {
res = i + 1;
break;
}
if(d[i]%n!=0)a[i]++;
a[i] += d[i] / n;
if (a[i] < cnt) {
cnt = a[i];
res = i + 1;
}
//printf("a[%d]=%d\n", i, a[i]);
}
printf("%d", res);
return 0;
}