导读就爱阅读网友为您分享以下“约瑟夫环每隔两个循环删除数组元素--frcsdn”资讯希望对您有所帮助感谢您对92to.com的支持!
C/C++面试之算法系列约瑟夫环每隔两个循环删除数组元素求最后删除者的下标问题
×××××××××××××××××××××××××××××××××
有一个数组a[1000]存放0--1000;要求每隔二个数删掉一个数到末尾时循环至开头继续进行求最后一个被删掉的数的原始下标位置原来的数可能是无序的另外数是否重复从题意无法确定。
以8个数为例
{0,1,2,3,4,5,6,7} 0-->1-->2 删 除 -->3-->4-->5(删除)-->6-->7-->0 删除
1
如此循环直到最后一个数被删除。
考点
本题的关键是如何理解删除的概念一种是将其彻底删除将后面未删除的全部前移这将浪费大量的时间用来移动后续数据另外一种只是仍然存在但已经失去意义遍历过程中不管之。
另外一个关键是如何在移动的过程中保持数据的原始下标因为数据本身可能是无序的下标和数据可能没有关系并且还可能重复
性能分析
时间效率循环队列法由于每次扫描的数都是未删除的时间整体效率最高标志数组法只是将此数标记为删除了但遍历时仍然要扫描链表法要建立链时间效率低
空间效率标志数组法未申请额外的空间空间效率最高循环队列法至少申请第一次未删除的空间另外作为接口函数来实现的话 由于新申请的空间不能与传入的数组地址相连 因此有局限性链表法额外建立链表空间效率最低
约束因素
2
对于只读数组普通的标志法都不能用了将高位置1遍历完后清除的方法借鉴意义最高 时间和空间效率最均衡链表法可以处理只读数组的问题循环队列法此时无法实现当然对于标志法可以额外申请空间保存标志也可以处理只读问题但空间效率下来了
面试中的最优选择
将高位置1遍历完后清除效率最高
数组方式二的优化版本三层while程序的逻辑功能划分明确
数组方式一的优化版本程序的结构易懂清晰
循环队列法最难想到个人认为相对于标志数组更有创新性
××××××××××××××××××××××××××××××××
方法1访问原数组置删除标志
这题目如果是面试题那考的就是用数组增加难度的。
××××××××××××××××××××××××××××××××
数组方式一const int size=1000;void ArrayTest1 (void)
{
3
int arr[size];int currentSize=size; //指示当前数组中还剩余有效元素的个数 为1时表示删除/完毕int count=0; //计数用for(int k=0;k<size;k++)
{arr[k]=k;
}
// i用循环计数终止条件是删除的只剩最后一个数了for(int i=0;(i<size) && (currentSize!=1);i=(i+1)%size)
{if(a rr[i]!=-1) //1为已经删除的标志未删除对之计数 已经删除的则看下一个
{
//按照计数间隔计数达到间隔时删除数据if(c o unt>=0 && c o unt<2)
{count++;
}else if( count==2) //逻辑有点乱
4
{arr[i]=-1;//将此元素做上标记表示删除此时的元素curre ntSize--;//有效元素减一count=0;//并将计数值归零
}
}
}for(int j=0;j<size;j++) //浪费时间啊
{if(a rr[j]!=-1)
{cout<<”the result is :”<<j<<endl;break;
}
}
}
优化版本宏定义意义明确更改方便是良好的编程习惯要在笔试面试中展现这种特点
删除数据时保存了其位置和实际的数据值无需最后一次扫描
三层判断条件功能清晰 总数是否删除是否达到间隔
5
值
#define SIZE 1000
#define STEP 2
#define DELFLAG(SIZE+1)void ArrayTest1Opt(void)
{int arr[SIZE];int currentSize=SIZE; //指示当前数组中还剩余有效元素的个数为0时表示删除/完毕int count=0; //计数用int i=0;int lastdelindex= 0; //用来保存每次删除值的位置不用留最后一个然后遍历int lastdelvalue = 0; //用来保存每次删除值不用留最后一个然后遍历for(int k=0;k<SIZE;k++)
{arr[k]=k;
}
// i用循环计数终止条件是删除所有的数了
6
//for(int i=0;currentSize!=0; i=(i+1)%SIZE)while(curre ntSize!=0)
{if(arr[i]!=DELFLAG) //DELFLAG为已经删除的标志未删除对之计数 已经/删除的则看下一个
{
//按照计数间隔计数达到间隔时删除数据if(c o u nt++==S TE P) //注意的位置
{lastdelindex=i; //用来保存每次删除值的位置lastdelvalue = arr[i] ; //用来保存每次删除值的位置arr[i]=DELFLAG;//将此元素做上标记表示删除此时的元素curre ntSize--;//有效元素减一count=0;//并将计数值归零
}
}i=(i+1)%SIZE;
}cout<<”the original array location of the last del
7
value is:“<<lastdel<<e ndl;
}
××××××××××××××××××××××××××××××××
数组方式二两重w h i le循环将间隔计数的直接
写成了程序未用循环这样移植性差了
//#define SIZE 1000
//#define STEP 2
//#define DELFLAG(SIZE+1)void ArrayTest2(void)
{int a rr[S IZE];for(int i=0;i<SIZE;++i)arr[i]=i; //实际情况并非一定如此啊int j=0;int count=0;while(count<S IZE-1) // 999保留了最后一个未删除的数
{
8
while(arr[j%1000]==DELFLAG)j=(++j)%SIZE;j=(++j)%SIZE; //第一个未访问的数while(arr[j%SIZE]==DELFLAG)j=(++j)%SIZE;j=(++j)%SIZE; //第二个未访问的数while(arr[j%SIZE]==DELFLAG)j=(++j)%SIZE;arr[j]=DELFLAG; //删除第三个未访问的数++c o u nt;
}while(arr[j]==DELFLAG) //扫描最后一个未删除的数j=(++j)%SIZE;cout<<j<<endl;
}
9
LetBox此次促销依然是AMD Ryzen处理器+NVME硬盘+HDD大硬盘,以前是5TB月流量,现在免费升级到10TB月流量。另外还有返余额的活动,如果月付,月付多少返多少;如果季付或者半年付,返25%;如果年付,返10%。依然全部KVM虚拟化,可自定义ISO系统。需要大硬盘vps、大流量vps、便宜AMD VPS的朋友不要错过了。不过LetBox对帐号审核严格,最好注册邮箱和paypal帐号...
妮妮云的来历妮妮云是 789 陈总 张总 三方共同投资建立的网站 本着“良心 便宜 稳定”的初衷 为小白用户避免被坑妮妮云的市场定位妮妮云主要代理市场稳定速度的云服务器产品,避免新手购买云服务器的时候众多商家不知道如何选择,妮妮云就帮你选择好了产品,无需承担购买风险,不用担心出现被跑路 被诈骗的情况。妮妮云的售后保证妮妮云退款 通过于合作商的友好协商,云服务器提供2天内全额退款,超过2天不退款 物...
tmhhost放出了2021年的端午佳节+618年中大促的优惠活动:日本软银、洛杉矶200G高防cn2 gia、洛杉矶三网cn2 gia、香港200M直连BGP、韩国cn2,全都是高端优化线路,所有这些VPS直接8折,部分已经做了季付8折然后再在此基础上继续8折(也就是6.4折)。 官方网站:https://www.tmhhost.com 香港BGP线路VPS ,200M带宽 200M带...