4.链表部分练习题

2020-10-07  本文已影响0人  据分专家

1.约瑟夫问题

约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3。

本题可使用循环链表解决
设置一个节点firsthead指向被删除节点
一个helper节点指向被删除节点的前一个节点
在下列代码中
在构建循环链表时,firsthead.next=第一个节点
在游戏开始时,需要使得firsthead=第一个节点

package com.zhiyang.linkedlist;

public class Josepfu {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        CircleLinkedList circleLinkedList = new CircleLinkedList();
        circleLinkedList.addBoy(5);
        // circleLinkedList.showList();
        circleLinkedList.countBoy(1, 2, 5);

    }

}

class CircleLinkedList {
    private Boy firsthead = null;

    public void addBoy(int n) {
        firsthead = new Boy(-1);
        if (n < 1) {
            System.out.println("人数过少");
            return;
        }
        Boy curBoy = firsthead;
        for (int i = 1; i <= n; i++) {
            Boy boy = new Boy(i);
            curBoy.next = boy;
            boy.next = firsthead.next;
            curBoy = curBoy.next;
        }
    }

    // 遍历环形链表
    public void showList() {
        if (firsthead == null) {
            return;

        }

        Boy curBoy = firsthead.next;
        while (true) {
            System.out.printf("小孩的编号%d\n", curBoy.getNo());
            if (curBoy.next == firsthead.next) {
                break;
            }
            curBoy = curBoy.next;
        }

    }

    // 根据用户输入,计算小孩出圈顺序
    /**
     * 
     * <p>
     * Title: countBoy
     * </p>
     * <p>
     * Description:
     * </p>
     * void
     * 
     * @param startno  从第几个小孩开始
     * @param countNum 数几个出圈
     * @param nums     总共多少人
     */
    public void countBoy(int startno, int countNum, int nums) {
        if (firsthead == null || startno < 1 || startno > nums) {
            System.out.println("参数错误");
            return;
        }

        // 创建一个辅助指针,帮助完成小孩出圈
        Boy helperBoy = firsthead.next;
        while (true) {
            if (helperBoy.next == firsthead.next) {
                break;
            }
            helperBoy = helperBoy.next;
        }
        // 现在helperBoy=队列最后一个
        // 出圈前,需要先移动到statrno位置来
        System.out.printf("目前helper指向的节点是%d\n", helperBoy.getNo());
        System.out.printf("目前firsthead指向的节点是%d\n", firsthead.getNo());
        firsthead = firsthead.next;
        for (int j = 0; j < startno - 1; j++) {
            firsthead = firsthead.next;
            helperBoy = helperBoy.next;
        }
        System.out.printf("目前helper指向的节点是%d\n", helperBoy.getNo());
        System.out.printf("目前firsthead指向的节点是%d\n", firsthead.getNo());
        while (true) {
            if (helperBoy == firsthead) {
                break;
            }
            for (int j = 0; j < countNum - 1; j++) {
                firsthead = firsthead.next;
                helperBoy = helperBoy.next;
            }
            // 这是first指向的小孩就是要出圈的小孩
            System.out.printf("小孩%d出圈\n", firsthead.getNo());
            firsthead = firsthead.next;
            helperBoy.next = firsthead;
        }
        System.out.printf("最后留在圈中的小孩的节点%d", firsthead.getNo());
    }
}

class Boy {
    private int no;
    public Boy next;

    public Boy(int no) {
        super();
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

}

目前helper指向的节点是5
目前firsthead指向的节点是-1
目前helper指向的节点是5
目前firsthead指向的节点是1
小孩2出圈
小孩4出圈
小孩1出圈
小孩5出圈
最后留在圈中的小孩的节点3

上一篇下一篇

猜你喜欢

热点阅读