【C语言经典问题】约瑟夫环问题案例

题目案例

问题描述:N个人围成一圈,从第一个人开始报数,报到m的人出圈,剩下的人继续从1开始报数,报到m的人出圈;如此往复,直到所有人出圈。

思路(默认间隔3出圈)

首先明确的就是当序列表满是rear是!=front的并且rear+1就为front的值。
我们定义front指向第一个 rear表示最后一个画个图来表示吧。
在这里插入图片描述
此时front 指向的是1 rear指向的是2。当要是1伪出圈front就要+1因为没有到间隔3所以没有真正意义上的出圈此时front指向的就是2 rear+1时 1的值已经不是首了而是新一个数据表中的尾也就是将伪出圈的1的值放在rear指向的空间中。

序列呈现(上为front下为rear)

在这里插入图片描述
这里我建立了一个N为10的序列此时的front指向x rear指向的是10 (初始阶段)
front+1 rear+1
在这里插入图片描述
此时指向的是1表示1伪出圈将1的值给向rear所指向的X
当++数等于间隔数
在这里插入图片描述
此时front已经指向3 将三真出圈也就是将原先3的位置空下来rear++在这里插入图片描述
然后再继续++将front所指向的4的值进行伪出圈然后给向rear++指向的原先为3的空间当中这样就出现了新序列一步步的循环直到所有元素出圈。

之后最重要的就是环的实现:
没间隔三个就要取一个数出圈我们这样我们可以进行取余%。
当3间隔时,1%3=1 2%3=2 3%3=1 这样就形成了一个环。i = (i + 1) % m
顺序表也是如此

front = (front + 1) % (N + 1);

代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#define N 100
#include<stdio.h>
#include<stdlib.h>
void TR(int * Q, int m)
{
	int front = 0,rear = N, i = 0;
	while (front != rear)
	{
		front = (front + 1) % (N + 1);
		i = (i + 1) % m;
		if (!i)
		{
			printf("%d已出圈", Q[front]);
		}
		else
		{
			rear = (rear + 1) % (N + 1);
			Q[rear] = Q[front];
		}
	}
}
int main()
{
	int *Q;
	int m;
	Q = (int *)malloc((N + 1)*sizeof(int));
	for (int i = 1; i < N + 1; i++)
	{
		Q[i] = i;
	}
	printf("输入间隔层");
	scanf("%d",&m);
	TR(Q, m);
	return 0;
}

在这里插入图片描述

int findTheWinner(int n, int k) {
    vector<int> arr(n);
    for (int i = 0; i < n; ++i) arr[i] = i + 1;
    
    int i = 0;
    while (arr.size() > 1) {
        int pos = (i + k - 1) % arr.size();
        arr.erase(arr.begin() + pos);
        i = pos;
    }
    
    return arr[0];
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值