题意整理
- 给定一个环形数组,开始的时候,牛牛在起始位置。
- 每经过1分钟,环形数组中对应元素减去1,并且牛牛会沿着环形数组不断后移。
- 如果牛牛所在位置,元素值小于等于0,则返回对应位置下标。
方法一(模拟)
1.解题思路
- 用一个变量记录排队时间。
- 通过循环,模拟遍历环形数组,没执行一次,排队时间加一,如果对应下标元素值减去排队时间小于等于0,说明可以进入对应的门,直接返回。
测试数据较大的时候,运行超时。
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 返回牛牛最终是从第几个门进入食堂吃饭的 * @param n int整型 代表门的数量 * @param a int整型一维数组 代表每个门外等待的人数 * @return int整型 */ public int nowcoderQueue (int n, int[] a) { //记录排队时间 int time=0; for(int i=0;i<n;i=(i+1)%n){ //如果某个门排队人数小于等于0,说明可以进入,直接返回对应门的编号 if(a[i]-time<=0){ return i+1; } time++; } return -1; } }
3.复杂度分析
- 时间复杂度:假设数组中最小值为min,最多需要循环次,所以时间复杂度为。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为。
方法二(预处理+模拟)
1.解题思路
简单分析:
由于每经过一圈,如果还不能进入到对应的门,牛牛都会回到起始位置。所以我们可以预先计算出最小值,如果最小值大于n,说明牛牛仍然会回到起始位置,没回到起始位置一次,数组中所有元素就要减去相应的排队时间n,所以直接减去n的倍数,直到最小值小于等于n。
基本步骤:
- 计算数组最小值。
- 对数组进行预处理,如果最小值大于n,所有元素减去n的倍数,直到最小值小于等于n。
- 按方法一的方式进行循环。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 返回牛牛最终是从第几个门进入食堂吃饭的 * @param n int整型 代表门的数量 * @param a int整型一维数组 代表每个门外等待的人数 * @return int整型 */ public int nowcoderQueue (int n, int[] a) { //计算最小值 int min=Integer.MAX_VALUE; for(int i=0;i<n;i++){ min=Math.min(min,a[i]); } //如果最小值大于n,进行预处理 if(min>n){ int d=min/n*n; //将所有数减去n的倍数,直到最小值小于n for(int i=0;i<n;i++){ a[i]-=d; } } //记录排队时间 int time=0; for(int i=0;i<n;i=(i+1)%n){ //如果某个门排队人数小于等于0,说明可以进入,直接返回对应门的编号 if(a[i]-time<=0){ return i+1; } time++; } return -1; } }
3.复杂度分析
- 时间复杂度:假设数组中最小值为min,预处理之后,最多需要循环次,所以时间复杂度为。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为。