题目
1、题目描述
共有 n 名小伙伴一起做游戏。小伙伴们围成一圈,按 顺时针顺序 从 1 到 n 编号。确切地说,从第 i 名小伙伴顺时针移动一位会到达第 (i+1) 名小伙伴的位置,其中 1 <= i < n ,从第 n 名小伙伴顺时针移动一位会回到第 1 名小伙伴的位置。
游戏遵循如下规则:
( 1 ) (1) (1)从第 1 名小伙伴所在位置 开始 。
( 2 ) (2) (2)沿着顺时针方向数 k 名小伙伴,计数时需要 包含 起始时的那位小伙伴。逐个绕圈进行计数,一些小伙伴可能会被数过不止一次。
( 3 ) (3) (3)你数到的最后一名小伙伴需要离开圈子,并视作输掉游戏。
如果圈子中仍然有不止一名小伙伴,从刚刚输掉的小伙伴的 顺时针下一位 小伙伴 开始,回到步骤 2 继续执行。
( 4 ) (4) (4)否则,圈子中最后一名小伙伴赢得游戏。
( 5 ) (5) (5)给你参与游戏的小伙伴总数 n ,和一个整数 k ,返回游戏的获胜者。
例如:n = 5, k = 3;
2、原题链接
解题报告
方法一:循环队列
1、解题思路
(
1
)
(1)
(1) 小朋友们排排队形成一个圈,模拟游戏过程,从第一个小朋友往下找需要出圈的下朋友。一轮结束后从从刚刚输掉的小朋友的顺时针下一位小朋友开始,继续整个过程,直到就剩一个小朋友,游戏结束。
(
2
)
(2)
(2) 用循环队列链表来实现,分析游戏结束的条件可以知道当链表的下一个节点指向自己的时候,整个队列一定只剩下自己
2、解题方法
- 循环队列
2、代码详解
/*循环队列:链表*/
typedef struct Node{
int num;
struct Node *next;
}people;
int findTheWinner(int n, int k){
int i;
people *pre;
/*初始化*/
people *head = (people*)malloc(sizeof(people));
people *p = head;
head->num = 1;
head->next = NULL;
for(i = 2; i < n+1; ++i){
p->next = (people*)malloc(sizeof(people));
p = p->next;
p->num = i;
p->next = NULL;
}
pre = p;
p->next = head;
/*开始游戏*/
while(head->next != head){
p = head;
for(i = 1; i < k; ++i){
pre = p;
p = p->next;
}
if(p == head){
head = p->next;
pre->next = head;
free(p);
}else{
pre->next = p->next;
head = p->next;
free(p);
}
}
return head->num;
}
方法二:递归
/*递归算法*/
int findTheWinner(int n, int k){
if(n == 1) return 1;
int winner = findTheWinner(n-1, k) + k;
return winner % n == 0 ? n : winner % n;
}