这里是题目描述:剑指Offer-面试题62:圆圈中最后剩下的数字
本题叫做 “约瑟夫环问题” 有两种解法:1.模拟执行整个删除数字的流程 2.以数学规律解题。这里是LeetCode官网中的两种解题方法详细描述
方法一:ArrayList模拟执行整个流程
从理论上分析,使用链表时确定删除数字的位置需要O(n),删除该数字需要O(1),一共需要执行n-1次删除;使用ArrayList确定删除数字的位置需要O(1),删除该数字需要O(n)(因为需要对被删除后面的数字移位),进行整个流程的模拟的时间复杂度都是O(n2),但是使用链表时会超出时间复杂度,使用ArrayList不会
class Solution {
//基于ArrayList
public int lastRemaining(int n, int m) {
if(n==1)
{
return 0;
}
ArrayList<Integer> arrayList=new ArrayList<>();
for(int i=0;i<n;i++)
{
arrayList.add(i);
}
int curIndex=0;
while(arrayList.size()>1)
{
int delIndex=(curIndex+m-1)%arrayList.size(); //计算要移除的元素的下标
arrayList.remove(delIndex); //移除
curIndex=delIndex;
}
return arrayList.get(0);
}
}
时间复杂度:O(n2)
空间复杂度:O(n)
方法二:使用数学方法解题
class Solution {
//基于数学方法
public int lastRemaining(int n, int m) {
if(n==1)
{
return 0;
}
int ans=0; //最后剩余的元素下标肯定为0
for(int l=2;l<=n;l++) //从要恢复的数组长度为2开始
{
ans=(ans+m)%l;
}
return ans;
}
}
时间复杂度:O(n)
空间复杂度:O(1)