蓝桥杯-第九届决赛——约瑟夫环

本文探讨约瑟夫环问题,介绍三种解决方法:数组迭代、列表移除及约瑟夫公式应用。通过实例演示每种方法的具体实现,对比其优劣,帮助读者深入理解并掌握约瑟夫环问题的解决技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

约瑟夫环

n 个人的编号是 1~n,如果他们依编号按顺时针排成一个圆圈,从编号是1的人开始顺时针报数。
(报数是从1报起)当报到 k 的时候,这个人就退出游戏圈。下一个人重新从1开始报数。
求最后剩下的人的编号。这就是著名的约瑟夫环问题。
 
本题目就是已知 n,k 的情况下,求最后剩下的人的编号。
 
题目的输入是一行,2个空格分开的整数n, k
要求输出一个整数,表示最后剩下的人的编号。
 
约定:0 < n,k < 1百万
 
例如输入:
10 3
 
程序应该输出:
4
 
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms
 
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

思路1:可以用数组变0去掉赋值给新的数组,然后再继续变0赋给新数组。

当最后剩下的长度为2也就是余一个数的时候,输出即可。

import java.util.Scanner;
/**
 * 数组
 */
public class Main {

	public static int n,k;
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		k = in.nextInt();
		int [] a = new int [n+1];
		for(int i=1;i<=n;i++){
			a[i] = i;
		}
		dfs(a,0);
	}
	/**
	 * 数组变0去掉赋值给新数组
	 * @param a新的数组
	 * @param count数到那个数了
	 */
	private static void dfs(int[] a,int count) {
		// TODO Auto-generated method stub
		if(a.length<=2){
			System.out.println(a[1]);
			return;
		}
		int count1 = 0;
		for(int i=1;i<a.length;i++){
			if(a[i]!=0){
				count++;
				if(count==k){
					count1++;
					a[i] = 0;
					count = 0;
				}
			}
		}
		int [] b = new int [a.length-count1];
		int j = 1;
		for(int i=1;i<a.length;i++){
			if(a[i]!=0){
				b[j] = a[i];
				j++;
			}
		}
		dfs(b,count);
	}
}

思路2: 可以用list集合,一个一个remove然后下标变动,当余下一个的时候,输出即可。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
 * list集合
 */
public class test {

	public static int n,k;
	public static List list = new ArrayList();
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		k = in.nextInt();
		for(int i=1;i<=n;i++)
			list.add(i);
		int temp = 0;
		for(int i=0;list.size()!=1;i++){
			if(i == list.size()) 
				i = 0;
			temp++;
			if(temp%k==0){
				list.remove(i);
				i--;
			}
		}
		System.out.println(list.get(0));
	}
}

思路3: 既然是约瑟夫问题,可以用约瑟夫公式。

公式来自优快云  作者:陈浅墨 原文:https://blog.youkuaiyun.com/u011500062/article/details/72855826

import java.util.Scanner;

/**
 * 公式
 */
public class test1 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int k = in.nextInt();
		System.out.println(cir(n,k));
	}
	
	public static int cir(int n,int m){
	    int p=0;
	    for(int i=2;i<=n;i++){
	        p=(p+m)%i;
	    }
	    return p+1;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萤火的微亮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值