题目案例
问题描述: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];
}