7-28 猴子选大王 (20 分)

法一:定义一个猴子个数大小的数组,其值均为1,代表初始时猴子都在圈中,随着报数的进行,报数为3的猴子对应的数组值为0,再进行新一轮报数,最终,当只有一个数组值为1时,结束循环,其为猴子大王。

import java.util.Scanner;
import java.lang.Math;
import java.util.HashMap;
import java.util.Map;
public class Main {
    public static void main (String [] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int [] index = new int[N];
        for (int i = 0; i < N; i++) {
            index[i] = 1;
        }
        int n = N; //圈子中剩余的猴子数目
        int b = 0; //报数
        while (n > 1) {
           for (int j = 0; j < N; j++) {
               b += index[j];
               if (b == 3) {
                   index[j] = 0;
                   n--;
                   b = 0;
               }
           }
        }
        for (int k = 0; k < N; k++) {
            if (index[k] != 0) {
                System.out.println(k+1);
            }
        }
    }
}

法二:约瑟夫问题,也是每次剔除一个报数为m的猴子(需要剔除n次),有递推公式,p(x) = (x + m ) % i;x是倒数第i轮循环中猴王的索引,i是该轮循环所包含的猴子总数,p(x)是倒数第i-1轮循环中猴王的索引下标,最后一轮循环,剩下一个猴王,其索引为0,即i=1,x=0
参考文章:https://blog.csdn.net/u011954296/article/details/51351982

import java.util.Scanner;
import java.lang.Math;
public class Main {
    public static void main (String [] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int result = 0;//猴王最后一轮循环的索引
        //从倒数第二轮循环开始,倒数第n轮也就是初始状态
        for (int i = 2; i <= n; i++) {
            result = (result + 3) % i;
        }
        System.out.print(result + 1);
    }
}

法三:用数组来模拟循环链表进行,last代表检测指针test上一次所在的位置,便于之后更新节点找对位置(因为删除节点之后,链表中间会有跳跃,只用一个test来进行的话,只能找到test-1的节点,中间有跳跃的话会使得代码报错)。数组中的值代表本只猴子的下一只猴子索引,当本只猴子的下一只猴子是自己时,循环结束,找到了猴子王。

import java.util.Scanner;
import java.lang.Math;
public class Main {
    public static void main (String [] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = 1;//用于计数(相当于报数)
        int [] node = new int [n];
        for (int i = 0; i < n -1; i++) {
            node[i] = i + 1;
        }
        int test = 0;
        int last;
        while (test != node[test]) {
            last = test;
            test = node[test];
            k++;
            if (k == 3) {
                node[last] = node[test]; //模拟删除节点,也就是记录删除节点的下一个节点的索引
                k = 0;//此时该节点已经报数为3,为了下一个节点报数为1,应该重置为0
            }
        }
        System.out.println(test + 1);
    }
}

贴个自己画的图,怕之后忘记了!节点左边是自己的索引,右边是下一只猴子的索引。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值