三种方法求解约瑟夫环问题

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

方法1:使用stl::list模拟环形链表,参考剑指offer

代码:

#include <iostream>
#include <list>
using namespace std;

int lastNumber(unsigned int n,unsigned int m ){
	if(n < 1 || m < 1)
		return -1;
	list<int> lNum;
	int i=0;
	for( i=0;i < n;i ++ ){
		lNum.push_back(i);
	}
	list<int>::iterator cur=lNum.begin();
	while(lNum.size() > 1){
		//每次都为i 开始值 ,m值考虑好长时间,这次记住了
		for(i=1;i<m;i++){
			cur++;
			if(lNum.end() == cur){
				cur = lNum.begin();
			}
		}
		list<int>::iterator next = ++cur;
		if(next == lNum.end())
			next = lNum.begin();
		cout<< * (--cur);
		lNum.erase(cur);
		cur = next;
	}
	return *cur;

}

int main()
{
	cout<<endl<<lastNumber(5,3);
    return 0;
}

运行结果:

2 使用环形链表

#include <iostream>
#include <list>
using namespace std;

typedef struct list{
	int data;
	struct list * pNext;
}List,*pList;

void createList(pList &pHead ,unsigned int m, unsigned int n){
	if(m < 1 || n <1 )
		return ;
	pList p=pHead,q;
	bool isFirst = true;
	for(int i=0;i < m ;i++){
		q=(pList)malloc(sizeof(List));
		q->data= i ;
		q->pNext = NULL;
		if(isFirst){
			p=pHead=q;
			isFirst = false;
		}else{
			p->pNext =  q;
			p = q;
		}
	}
	q->pNext = pHead;

}
void deleteNum(pList &pHead,unsigned int n){
	pList p = pHead,q;
	int i=0;
	while(p->pNext != p){
		for(i=1;i < n ;i++){
			p = p->pNext;

		}
		cout<< p ->data << " ";
		q=p->pNext;
		p->data = p->pNext->data;
		p->pNext=p->pNext->pNext;
		free(q);
	}
	cout<<endl<<p->data<<endl;

}

void print(pList &pHead){
	pList p = pHead;
	do{
		cout<< p->data<< " ";
		p = p->pNext;
	}while(p !=pHead );
}

int main()
{
	pList head=NULL;
	createList(head ,5 ,3);
	cout<<"原链表为:";
	print(head);
	cout<<endl<<"依次删除顺序为:"<<endl;
	deleteNum(head,3);
	//print(head);
    return 0;
}

运行结果为:

3 利用递归 ,查找其中规律

#include <iostream>
#include <list>
using namespace std;

//使用for循环解决
int lastRemainNum(unsigned int m , unsigned int n){
	if(m < 1 || n < 1)
		return -1;
	int last = 0;
	for(int i=2; i <= m ;i++){
		last =(last  + n) % i;
	//	cout << last << " ";
	}

	return last;
}

//使用递归
int lastNum(unsigned int m,unsigned int n){
	if(m < 1 || n < 1)
		return -1;
	if(m == 1)
		return 0;
	return (lastNum(m-1,n) + n) % m;

}

int main()
{   cout<< lastNum(5,3);
    cout<<  lastRemainNum(5,3);
    return 0;
}

运行结果:

三种方法求解约瑟夫环问题,布布扣,bubuko.com

时间: 2024-08-03 11:28:02

三种方法求解约瑟夫环问题的相关文章

三种方法求解两个数组的交集

package com.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; //求两个数组的交集 public class FindIntersectionBetweenTwoArrays { //算法一:暴力搜索,时间复杂度O(n^2),空间复杂度O(1) public ArrayList

解决约瑟夫环的三种方法

假设有一圈石子,从1到n比较.然后依次每隔一个石子选出一个,直到剩余一个:问最后选出的石子的编号是多少: (至少)有三种方法可以解决这个问题:如下面的代码所示: object App extends App {   def native(n: Int): Int = {     def dispatch(pre: List[Int], list: List[Int]): List[Int] =       list match {         case Nil => pre         

用旭日图展示数据的三种方法

什么是旭日图? 旭日图(Sunburst Chart)是一种现代饼图,它超越传统的饼图和环图,能表达清晰的层级和归属关系,以父子层次结构来显示数据构成情况.旭日图中,离远点越近表示级别越高,相邻两层中,是内层包含外层的关系. 在实际项目中使用旭日图,可以更细分溯源分析数据,真正了解数据的具体构成.而且,旭日图不仅数据直观,而且图表用起来特别炫酷,分分钟拉高数据汇报的颜值!很多数据场景都适合用旭日图,比如,在销售汇总报告中,方便看到每个店铺的销售业绩分布(如下图): 做旭日图的三种方法 1. 用E

Struts2关于Action的系统训练6关于action接收参数的三种方法

我们知道,action在web开发中起到了控制器的作用,通过接收客户端传来的参数,执行不同的模块才实现操作,所以说接收参数是很重要的一环,只有接收前端的参数,才能执行数据库的操作等后台业务逻辑,那么就开始一一展示这三种方法吧(只用看action类的编写即可) 1第一种方式:UserAction.java package com.bjsxt.struts2.user.action; import com.opensymphony.xwork2.ActionSupport; public class

分区自动挂载的三种方法

一.修改/etc/rc.local配置文件追加类似命令:mount /dev/sda1  /sda1 到配置文件最后一行 二,修改/etc/fstab配置文件追加类似命令:/dev/sda1   /sda1  ext4   defaults   0  0 到配置文件中 三,安装autofs服务yum install autofs 追加类似命令:sda1   -fstype=ext4  :/dev/sda1 到配置/etc/autofs.misc文件中重启服务: service autofs re

VMWARE虚拟机不能上网三种方法分析

bridged(桥接模式). NAT(网络地址转换模式) host-only(主机模式). 理论理解: 1.bridged(桥接模式) 在这处模式下,虚拟机等同于网络内的一台物理主机,可对手动设置IP,子网掩码,DNS,且IP地址要和主机的IP在同一网段内.这样,虚拟机就和主机如同连在一个HUB上的两台计算机,只要主机能上网,虚拟机也会在这种模式下上网. 2.host-only(主机模式) 在host-only模式中,所有的虚拟系统是可以相互通信的,但虚拟系统和真实的网络是被隔离开的. 提示:在

pdf文件怎么编辑 如何编辑pdf文件的三种方法

pdf文件越来越流行,工作中经常遇到需要修改pdf文件的情况.一般人的电脑上都为pdf文件安装了一个pdf阅读器,可它只能用来阅读查看pdf文件,并不能满足人们的编辑需求.那么pdf文件怎么编辑?下面小编给大家讲讲关于如何编辑pdf文件的三种方法.     方法一:直接编辑,一步到位     如果要对pdf文件进行编辑,我们则需要安装pdf编辑器.最新版的迅捷pdf编辑器可以编辑pdf文件中的任何内容,包括文字.图片.页眉页脚.添加注释等等.迅捷pdf编辑器如何编辑pdf文件?     首先需要

Android TextView里直接显示图片的三种方法

方法一:重写TextView的onDraw方法,也挺直观就是不太好控制显示完图片后再显示字体所占空间的位置关系.一般如果字体是在图片上重叠的推荐这样写.时间关系,这个不付源码了. 方法二:利用TextView支持部分Html的特性,直接用api赋图片.代码如下: //第一种方法在TextView中显示图片 String html = "<img src='" + R.drawable.circle + "'/>"; ImageGetter imgGett

Linux更新内核的三种方法

Centos内核升级的三种方法 在基于CentOS平台的工作过程中,难免有时需要升级或者降级内核以验证功能.调试性能或者更新整个系统.如果从头重新编译一个内核,由于现在内核特性越来越复杂,依赖的库或者工具也不少,加之重新编译耗时不菲,了解更新内核的多种方式就显得尤为必要.下面根据笔者最近的工作,总结了三种方法,供大家参考. 方法一 如果机器不能联网,可以下载现有内核包到本地机器,直接在本地更新 1.从http://ftp.scientificlinux.org/linux/scientific/