每日一题(21)猴子选大王

一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?

输入格式:

输入在一行中给一个正整数N(≤1000)。

输出格式:

在一行中输出当选猴王的编号。

输入样例:

11

输出样例:

7

 

问题分析

这个问题实际上是一个经典的约瑟夫环(Josephus Problem)问题。约瑟夫环是一个数学的应用问题:已知n个人(编号从1到n)围成一个圈,从第1个人开始报数,报到m的人出局,剩下的人继续从1开始报数,如此往复,直到只剩下一个人。

在本题中,我们有以下条件:

  • n个猴子围成一圈(在样例中n=11)
  • 从第1号猴子开始报数
  • 每次数到3的猴子被淘汰(即m=3)
  • 最后一个留下的猴子成为猴王

我们需要模拟这个过程,找出最后留下的猴子的编号。

解题思路

解决约瑟夫环问题有多种方法:

  1. 直接模拟法:使用一个数据结构(如链表)来表示圈子,然后模拟报数和删除的过程。
  2. 递归求解法:使用数学递推公式求解。约瑟夫环问题有一个著名的递推关系:

f(n, m) = (f(n-1, m) + m) % n,其中f(n, m)表示n个人、报数到m时最后剩下的人的编号。

     3.循环队列法:使用循环队列模拟报数和删除过程。

在这里,我们将采用直接模拟法,使用LinkedList来表示猴子圈,并模拟整个报数和淘汰的过程

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = 3;
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 1; i <= n; i++) {
            list.add(i);
        }

        int cnt = 0, index = 0;
        while (!list.isEmpty()) {
            cnt++;
            index++;
            if(index>list.size()) index = 1;
            if (cnt == m) {
                if(list.size()!=1) {
                    list.remove(index - 1);
                    index--;
                    cnt = 0;
                }
                else System.out.println(list.removeLast());
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值