蓝桥杯 奥运会开幕式 (C && Java)

解题思路:这是一道典型的约瑟夫环问题,依次筛选出对应号码的学生,留至最后的即为获胜者,由于要求链表,用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 + "]";
	}
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值