约瑟夫环

已知N个人围成一个圆圈,每隔M个元素,就清除该元素,剩下的继续:每隔M个元素,就清除该元素,直到元素只有(M-1)个为止。

n个人排成一圈。从某个人开始,按顺时针方向依次编号。
从编号为1的人开始顺时针“一二一”报数,报到2的人退出圈子。这样不断循环下去,圈子里的人将不断减少。由于人的个数是有限的,因此最终会剩下一个人。

试问最后剩下的人最开始的编号。

约瑟夫环是一个循环列表问题。我们用三种线性数据结构来分别实现,同时打印算法用时。

第一种:移除指定位置的元素,每隔N个元素就清除,使用List<T>的RemoveAt(index)

第二种:使用T[] array,bool[] flagArray,第一个数组代表集合数据,第二个数组代表是否已删除标记

第三种:我们使用元组列表来实现Tuple<T,bool> 第一项代表集合数据,第二项代表是否已删除标记

新建.net 5.0控制台应用程序JosephRingDemo,输入测试程序如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;namespace JosephRingDemo
{class Program{static void Main(string[] args){int divide = 3;//列表List<string> stringlist = new List<string>() { "大魔法师", "山丘之王", "圣骑士", "血魔法师","剑圣", "先知", "牛头人酋长", "暗影猎手","死亡骑士", "巫妖", "地穴领主", "恐惧魔王","恶魔猎手", "丛林守护者", "守望者", "月之女祭司","驯兽师", "黑暗游侠", "深渊魔王", "娜迦女海巫","火焰领主", "炼金术士", "地精修补匠", "熊猫酒仙","AA","BB","CC","DD","EE","FF","GG","HH","II","JJ","KK","LL","MM","NN","OO","PP","QQ","RR","SS","TT","UU","VV","WW","XX","YY","ZZ"};//数组string[] array = stringlist.ToArray();bool[] flagArray = new bool[array.Length];//元组的第一项代表姓名[string],第二项代表是否已删除标志[bool](默认都未删除)List<Tuple<string, bool>> tupleList = new List<Tuple<string, bool>>();for (int i = 0; i < stringlist.Count; i++){tupleList.Add(Tuple.Create(stringlist[i], false));}JosephRing(stringlist, divide);Console.WriteLine($"【使用List<string>集合】当前集合剩余元素【{string.Join(",", stringlist)}】");JosephRing(array, flagArray, divide);List<string> tempList = new List<string>();for (int i = 0; i < array.Length; i++){if (!flagArray[i]) {tempList.Add(array[i]);}}Console.WriteLine($"【使用string[]和bool[]集合】当前集合剩余元素【{string.Join(",", tempList)}】");JosephRing(tupleList, divide);Console.WriteLine($"【使用List<Tuple<string, bool>>集合】当前集合剩余元素【{string.Join(",", tupleList.FindAll(tuple => !tuple.Item2).Select(tuple => tuple.Item1))}】");Console.ReadLine();}/// <summary>/// 约瑟夫环一:【使用列表集合】每隔divide个元素就从集合中删除/// </summary>/// <param name="list">集合</param>/// <param name="divide">分割计数,每隔几个移除</param>static void JosephRing(List<string> list, int divide){if (list == null) {throw new ArgumentNullException("集合list不能为空");}if (divide <= 0) {throw new ArgumentOutOfRangeException("分割计数必须为正整数");}Contract.EndContractBlock();Stopwatch stopwatch = Stopwatch.StartNew();int cnt = 0;//记录移除的元素集合List<string> removeList = new List<string>();//如果集合的个数 大于 (分割数-1)while (list.Count > divide - 1){for (int index = 0; index < list.Count; index++){cnt++;if (cnt >= divide){//Console.WriteLine($"【{list[index]}】被移除...");removeList.Add(list[index]);list.RemoveAt(index);index--;cnt = 0;}}}Console.WriteLine($"---约瑟夫环一:依次移除的元素集合【{string.Join(",", removeList)}】");Console.WriteLine($"---约瑟夫环一:【使用列表集合】,算法用时【{stopwatch.Elapsed.TotalMilliseconds}】ms");}/// <summary>/// 约瑟夫环二:【使用数组】隔divide个元素就将元素状态设置为已删除/// </summary>/// <param name="array">姓名数组,必须与是否删除标记数组flagArray长度一致</param>/// <param name="flagArray">标记数组,必须与姓名数组array长度一致</param>/// <param name="divide"></param>static void JosephRing(string[] array, bool[] flagArray, int divide) {if (array == null){throw new ArgumentNullException("数组array不能为空");}if (flagArray == null){throw new ArgumentNullException("数组flagArray不能为空");}if (array.Length != flagArray.Length) {throw new ArgumentOutOfRangeException($"对应数组的元素个数不一致:【{array.Length}】vs【{flagArray.Length}】");}if (divide <= 0){throw new ArgumentOutOfRangeException("分割计数必须为正整数");}Contract.EndContractBlock();Stopwatch stopwatch = Stopwatch.StartNew();int cnt = 0;//记录移除的元素集合List<string> removeList = new List<string>();//如果存在未删除状态的集合个数 大于 (分割数-1)while (flagArray.ToList().FindAll(element => !element).Count > divide - 1){for (int index = 0; index < array.Length; index++){//如果某个元素没有被删除if (!flagArray[index]){cnt++;}if (cnt >= divide){//Console.WriteLine($"【{array[index]}】被标记为已删除状态...");removeList.Add(array[index]);flagArray[index] = true;cnt = 0;}}}Console.WriteLine($"---约瑟夫环二:依次移除的元素集合【{string.Join(",", removeList)}】");Console.WriteLine($"---约瑟夫环二:【使用数组】,算法用时【{stopwatch.Elapsed.TotalMilliseconds}】ms");}/// <summary>/// 约瑟夫环三:【使用元组集合】每隔divide个元素就将元素状态设置为已删除/// </summary>/// <param name="tupleList"></param>/// <param name="divide"></param>static void JosephRing(List<Tuple<string, bool>> tupleList, int divide){if (tupleList == null){throw new ArgumentNullException("集合tupleList不能为空");}if (divide <= 0){throw new ArgumentOutOfRangeException("分割计数必须为正整数");}Contract.EndContractBlock();Stopwatch stopwatch = Stopwatch.StartNew();int cnt = 0;//记录移除的元素集合List<string> removeList = new List<string>();//如果存在未删除状态的集合个数 大于 (分割数-1)while (tupleList.FindAll(tuple => !tuple.Item2).Count > divide - 1){for (int index = 0; index < tupleList.Count; index++){//如果某个元素没有被删除if (!tupleList[index].Item2){cnt++;}if (cnt >= divide){//Console.WriteLine($"【{tupleList[index].Item1}】被标记为已删除状态...");removeList.Add(tupleList[index].Item1);//注意 不能使用 tupleList[index].Item2 = true; 元组的第几项是只读的tupleList[index] = new Tuple<string, bool>(tupleList[index].Item1, true);cnt = 0;}}}Console.WriteLine($"---约瑟夫环三:依次移除的元素集合【{string.Join(",", removeList)}】");Console.WriteLine($"---约瑟夫环三:【使用元组集合】,算法用时【{stopwatch.Elapsed.TotalMilliseconds}】ms");}}
}

运行结果如图:

算法性能:元组----->数组----->列表

C#线性表约瑟夫环(Joseph Ring)相关推荐

  1. I00032 约瑟夫环(Joseph problem)

    有关约瑟夫环的介绍,可以参见百度百科的约瑟夫环. 程序中假定人数n小于100,输入数据为n和m.其中,n为人数,数到第m个人出局.输出出局人的顺序.输入数据为0和0时程序结束. AC的C语言程序如下: ...

  2. 数据结构——约瑟夫环(Joseph Circle)

    问题描述: 编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数).现在给定一个随机数m>0,从编号为1的人开始,按顺时针方向1开始顺序报数,报到m时停止.报m的人出圈 ...

  3. Algorithms_基础数据结构(04)_线性表之链表_单向循环链表约瑟夫环问题

    文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 结构 分析 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 tip:单向链表 约瑟夫问题 N个人围成一圈, ...

  4. 线性表进阶___约瑟夫环问题

    /*** 解决约瑟夫环问题:古代某法官要判决n个犯人,荒唐的法律:将犯人站成一个圈,从第S个人开始数起* 每数到第D个犯人,就拉出来处决,再从下一个开始数D个,数到的人再处决,直到剩下最后一个犯人予以 ...

  5. PTA 线性表 7-1 约瑟夫环(Josephus)问题(by Yan) (100分) 按出列次序输出每个人的编号

    7-1 约瑟夫环(Josephus)问题(by Yan) (100分) 编号为1,2,-,n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数).一开始任选一个正整数m作为报数上限值,从 ...

  6. 约瑟夫环问题2(顺序表+链表求解)

    1.背景知识 * 古代判官要判决number个罪犯的死刑,制定了一条荒谬的法律 * 将犯人站成一个圈,从start开始数起,每数到第distance * 个就处决他,依照此规律直到最后剩下一个人赦免. ...

  7. 单链表-两个线性表的合并1(破环原链表+尾插法)

    题意: 令L1 = (X1,X2,X3,X4-Xn), L2 = (y1,y2,y3,y4-ym);是两个线性表.采用带头节点的链表存储,设计一个算法合并L1,L2,结果放在线性表L3中,要求如下: ...

  8. UVA1363 LA3521 POJ2800 ZOJ2646 Joseph‘s Problem【约瑟夫环+数学】

    Joseph's Problem Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7906 Accepted: 2107 Desc ...

  9. 深度剖析Josephus ring(约瑟夫环)C语言版

    深度剖析Josephus ring(约瑟夫环)C语言版 鉴于C语言更适合展示算法的底层设计,并且便于读者的研究与思考,故而小编使用C语言来展示约瑟夫环的精巧与奥妙. Hello!!各位同学们,欢迎来到 ...

  10. hdu1443 Joseph(约瑟夫环)

    问题:有2k个人,前k个是好人,后k个是坏人,要求最小的m,使得k个坏人在好人之前. 思路: 约瑟夫环递归式为F(n,k)=(F(n-1,k) + k) mod n.其中F(n,k)表示n个人,每一次 ...

最新文章

  1. 三代测序的基本原理、组装方法和应用场景
  2. php.ini文件找不到
  3. java.nio.Buffer flip()方法
  4. 如何删除webstrom中生成的.idea wrokspace
  5. Python可以这样学(第二季:tkinter案例精选)-董付国-专题视频课程
  6. SQLi LABS Less-19
  7. 大企业都在用的开源 ForgeRock OpenAM 被曝预认证 RCE 0day
  8. golang 判断map的键key是否存在
  9. PCB加工文件—Gerber文件的导出(转载)
  10. 视频播放设计测试用例
  11. Menhera酱全套表情包
  12. 日语的汉(训读)字音读音便规则
  13. 测试发文章测试发文章
  14. 卷积神经网络残差计算
  15. Centos7.2安装搜狗拼音
  16. js接收java数组对象_js接收并转化Java中的数组对象的方法
  17. Webpack 常用知识点总结
  18. 无线传感器网络定位算法
  19. surface pro4-7安装黑苹果教程
  20. seaJS 简要介绍和完整例子

热门文章

  1. 社交网络叠加直播功能,会产生什么化学反应?
  2. 2019杭电多校 Snowy Smile hdu6638 (线段树最大子段和)
  3. 使用selenium爬取百合网
  4. 保存到千牛服务器的文件在哪里,压缩包里的文件保存后在哪里?
  5. mysql每五分钟取一次数据_mysql – 给定时间内每5分钟的平均数据
  6. 迅雷7计算机丢失xlfsio.dll,求大神帮忙,迅雷7出现的崩溃问题
  7. 记梦之三:我成了萧峰
  8. 纽约大学文科学院计算机,2016年美国大学文科排名大全
  9. 7-14 然后是几点 (15 分)有时候人们用四位数字表示一个时间,比如 1106 表示 11 点零 6 分。现在,你的程序要根据起始时间和流逝的时间计算出终止时间。
  10. 计算机研究院分所烟台,综合新闻_中科院计算所烟台分所 烟台中科网络技术研究所...