解题思路:这是一道典型的约瑟夫环问题,依次筛选出对应号码的学生,留至最后的即为获胜者,由于要求链表,用C来做会更容易理解。
解题难点:按照 约瑟夫环问题来做基本不会有什么太大的问题,最开始我没有考虑到号码为“1”的情况,提交后,有一组“9 1”的数据提示运算超时,然后我就一直在思考会不会是时间复杂度太高,我很困惑,这应该是测试数据里面最简单的一组数据,直接能计算出是最后一名学生获胜,为什么他会警告运算超时呢?最后我才发现,号码若为1,我的choose函数中循环“i+1永远不可能为1”,导致死循环,于是我利用分支语句做了相应判断,若号码为1,直接返回0,否则返回正确结果。
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
typedef struct Stu{
int num;
struct Stu* next;
}Stu;
void create (Stu* head,int n){
Stu *pre,*p;
int i;
//创建尾结点,每次移动并连接头指针
p = (Stu*)malloc(sizeof(Stu));
p->next = NULL;
for(i = 1;i <= n;i++){
//每次开辟活动结点,模拟每位同学
pre = (Stu*)malloc(sizeof(Stu));
pre->next = NULL;
//给活动结点赋值学号
pre->num = i;
//若头结点为空的连接情况
if(head->next == NULL){
head->next = pre;
p = pre;
p->next = head->next;
}
//若头结点不为空的连接情况
else{
p->next = pre;
p = pre;
p->next = head->next;
}
}
}
int choose (Stu* head,int m){
Stu* s;
int i = 1;
//创建活动结点
s = (Stu*)malloc(sizeof(Stu));
s->next = NULL;
s = head->next;
//选择号码分两种情况,1或者其他自然数,若为1,则一定是报到最后的一个人留下,所以直接返回0
if(m == 1){
return 0;
}
//若为其他自然数,则就进行依次循环筛选,
else{
while(s->next != s){
if(i+1 == m){
s->next = s->next->next;
i = 1;
s = s->next;
}
else{
i++;
s = s->next;
}
}
//返回最后的结果
return s->num;
}
}
int main(int argc, char *argv[]) {
int n,m;
Stu *head;
//创建头结点
head = (Stu*)malloc(sizeof(Stu));
head->next = NULL;
//依次输入学生人数以及要报到的号码
scanf("%d%d",&n,&m);
//先生成学生链表
create(head,n);
//根据号码的两种情况,输出对应结果
if(choose(head,m))
printf("%d",choose(head,m));
else
printf("%d",n);
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanf = new Scanner(System.in);
int n = scanf.nextInt();
int m = scanf.nextInt();
//创建链表对象
MinkedlistDemo Link = new MinkedlistDemo();
Link.create(Link.getHead(),n);
if(Link.choose(Link.getHead(),m) == 0)
System.out.println(n);
else
System.out.println(Link.choose(Link.getHead(),m));
}
}
//定义链表类
class MinkedlistDemo{
StuNode head = new StuNode(0);
public StuNode getHead() {
return head;
}
//创建学生链表
public void create (StuNode head,int n) {
StuNode temp = head;
for(int i = 1;i <= n;i++) {
StuNode pre = new StuNode(i);
temp.next = pre;
temp = pre;
}
temp.next = head.next;
}
//筛选方法
public int choose(StuNode head,int m) {
StuNode temp = head.next;
int i = 1;
if(m == 1)
return 0;
else {
while(temp.next != temp) {
if(i+1 == m){
temp.next = temp.next.next;
i = 1;
temp = temp.next;
}
else{
i++;
temp = temp.next;
}
}
return temp.num;
}
}
}
//学生定义结点
class StuNode{
public int num; //学生编号
public StuNode next; //指针结点
public StuNode(int num) {
super();
this.num = num;
}
@Override
public String toString() {
return "StuNode [num=" + num + "]";
}
}