我的编程挑战之报数问题

本文探讨了一个关于复杂报数问题的算法优化,从初始链表构建出发,通过巧妙的操作避免了O(n^2)的时间复杂度,最终实现了更高效的解决方案,解决了在特定规则下找出最后剩余的人数问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:有n个人编号1-n,按照顺时针方向围成一个圆圈。它们预先定义好两个整数x,y。先从1号顺时针方向开始报数,报到x的人出圈,再从x的逆时针方向的后一个人从1开始报数,报到y的人出圈,再从这个人的顺时针方向后一个人开始从1报数,报到x的人出圈,如此反复,直到最后剩下一个人为止,问最后剩下的那个人是几号? 比如n = 10, x = 3, y = 2,报数的过程如下 报数人 1, 2, 3  3出圈 报数人 2,1       1出圈 接着2,4 ,5       5出圈 接着4,2          2出圈 接着4,6,7       7出圈 接着6,4         4出圈 接着6,8,9      9出圈 接着8,6         6出圈 接着8,10,8    8出圈 剩余 10号。 输入n,x,y输出剩余的编号。 数据范围 1 < n <= 1000000,   1<=x,y<=1000000000。

我的代码如下:

思想是,先建立一个链表,每次按要求从中删除一个,当然这样可以很确定删除的是哪一个,最后剩下的那个就是所求结果。

using System;
using System.Collections.Generic;
public class Test
{
public static int remain(int n,int x,int y)
{
if(n==1)return 1;
List<int> ln = new List<int> ();
int i,j;
for(i=0;i<n;i++) ln.Add(i+1);
j=0;
int ti=0;
while(n>1){
j=j+1;
if(j==1){
ti=(ti+x-1)%n;
//Console.WriteLine("第{0}个,数字为{1}",ti,ln[ti]);
ln.RemoveAt(ti);
n=n-1;
if(ti>0) ti--;
else ti = n-1;
}
else{
j=j%2;
ti=(ti-(y-1))%n;
if(ti<0) ti+=n;
//Console.WriteLine("第{0}个,数字为{1}",ti,ln[ti]);
//Console.WriteLine(ln[ti]);
ln.RemoveAt(ti);
n--;
if(ti>=n) ti=ti-n;
}
}
return ln[0];
}

我本来以为这样耗时也就是O(n),当时没有想到对List进行操作是很费时间的,根据下标访问某个元素的耗时也是O(n),因此上述算法就变成了O(n^2),因此提交没有通过。

看到某高手的文章,才恍然大悟,原来还可以这样!






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值