Java中使用list解决约瑟夫问题(丢手绢问题)

其他解决方式:

Java中使用环形链表解决约瑟夫问题icon-default.png?t=M85Bhttps://blog.csdn.net/qq_35813811/article/details/127159914


前言

众所周知,约瑟夫问题又名丢手绢问题,是一个经典的算法问题。这里就以丢手绢问题来模拟约瑟夫问题的大致内容。问题的大致内容是:已知n个小孩(以编号1,2,3.....,n)围成一个圈。从编号为k的人开始报数,数到m的那个人出列,出列之后,剩下的人又继续报数,同时他的下一个人又从1开始报数,数到m的那个人又出列,剩下的人又继续报数。以此规律重复下去,直到小孩全部出列。

该问题除了使用链表来解决,在Java中还可以使用 list来解决问题。


 

一、思路分析

在该问题的list解决方案中,我们已经不需要重新创建链表和Chird类来解决问题了,我们使用数字代替每一个小孩。

在这里,我们假设有6个小孩,我们选择使用两个中间变量来对list进行遍历,分别是point和a,point为list的下标,a为目前报数的数字。

开始之前,创建两个list集合,一个用于存放未出列的小孩,一个存放已经出列的小孩。由于下标是从0开始,k是从1开始,所以这里对point要为k-1,并且a的值为0.当开始报数时,point对应的list的下标就是1号小孩,同时将a增加1。报完数之后,point增加1,指向第二个下标的元素,同时a也增加。

当报到第三个小孩时,a等于m,3号小孩出列。此时就将3号小孩添加进已经出列的小孩列表。

添加成功之后,point继续增加,当报数到4号小孩时,a又重新变为1,当六号小孩报完之后,此时又将point归0,从1号小孩开始循环。

 

此时又会遇到一个问题,如果我又循环到已经添加过的小孩怎么办呢?

这个时候就需要判断这个小孩是不是在已经被添加过的列表中了,如果小孩在已经添加的列表中,则跳过小孩,继续向下循环,直到将最后一个小孩添加进已出列的list中,程序执行完成。

二、代码实现

import java.util.*;

public class ListSolveJosephu {
    public static void main(String[] args) {
        listSolveJosephu(6, 1, 3);
    }

    public static void listSolveJosephu(int n, int k, int m) {
        //新建两个list
        List<Integer> list = new ArrayList<>();
        List<Integer> listFinal = new ArrayList<>();
        //添加人数
        for (int i = 0; i < n; i++) {
            list.add(i+1);
        }
        int point = k-1;
        int a = 1;
        //开始循环
        while (true) {
            //如果已出列列表包含则point增加之后跳过
            if (listFinal.contains(list.get(point))) {
                point++;
                if (point == list.size()) {
                    point = 0;
                }
                continue;
            }
            //如果a==m则向已出列list中增加元素
            if (a == m) {
                listFinal.add(list.get(point));
                a = 0;
            }
            if (listFinal.size() == list.size()) {
                break;
            }
            a++;
            point++;
            //如果point是list的长度之后,将point归零
            if (point == list.size()) {
                point = 0;
            }
        }
        //打印输出的结果
        for (int i = 0; i < listFinal.size(); i++) {
            System.out.println(listFinal.get(i));
        }
    }
}

总结

这里利用了Java中的list解决了约瑟夫问题,相比起制作链表的方式简化了很多,可以看出在解决实际问题之时,Java的高灵活性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

醉倾梦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值