第6题 约瑟夫环问题

题目: n个数字 (0,1,2,3, ... , n-1) 形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字。

第一个为当前数字本身,第二个为当前数字的下一个数字。

当一个数字删除后,从被删除数字的下一个继续删除第m个数字


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



此题目也叫约瑟夫环问题,是一个非常经典的问题,我认为此题意在考察面试者对于算法和数据结构的理解,

因为这道题既可以从算法角度解决,也可以从数据结构的角度寻找思路



上面这个例子,就是有9个人,每数5个人,就排除出去,最后会剩下8号

我们假设是编号是从1开始计数的


先从数据结构的角度思考:

为了以一种循环方式排列人群,构建一个循环链表,每个人与他下一个人之间有一个链接。整数 i 表示循环中的第 i 个人。生成一个唯一节点的循环链表之后,

在该节点后插入2到n节点。


#include<stdio.h>
#include<stdlib.h>

struct node {
	int id;
	struct node* next;
};

int josephus(int n, int m) {
	struct node* t = malloc(sizeof(struct node));
	struct node* x = t;

	t->id = 1;
	t->next = t;

	//构造循环链表并赋值
	int i;
	for(i=2; i<=n; i++) {
		x = (x->next = malloc(sizeof(struct node)));
		x->id = i;
		x->next = t;
	}

	//不断从这个链表中删除节点,直到剩下最后一个
	while(x != x->next) {
		for(i=1; i<m; i++) 
			x=x->next;

		x->next = x->next->next;
		n--;
	}

	return x->id;
}

int main() {
	printf("%d\n",josephus(9,5));
}


从算法角度考虑分为递归和非递归解决的方法:

本人愚钝,一直没有看懂这两种方法,但是先列出来吧,大家参考一下


递归的


int f(int n, int m)
{
  if (n > 1)
    return (m + f(n - 1, m)) % m;
  else
    return 0;
}


非递归的

int f(int n, int m)
{
    int i, r = 0;
    for (i = 2; i <= n; i++)
        r = (r + m) % i;
    return r+1;
}



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值