约瑟夫问题

约瑟夫问题描述如下:约瑟夫问题

解题思路如下:
用单循环链表模拟犯人,链表中的每一个节点代表一个犯人。假设总共有 n 个犯人,每隔 m 个犯人处决一个,起始位置是 k,那么从第 k 个节点开始遍历,遍历到第 m+1 个节点时,移除该节点。然后再从 1 遍历到 m+1……如此循环往复,直到只剩下一个节点,就是幸存的犯人。

代码如下:

/**
 * 约瑟夫问题
 * filename: JosephusProblem.java
 */
public class JosephusProblem {

    /**
     * 约瑟夫问题的解决方案
     * @param len 总人数
     * @param num 要跳过的人数
     * @param start 开始的位置
     *
     */
    public static void solution(int len, int num, int start){
        if(start < 1 || start > num)
            return;
        MyLinkedList mll = new MyLinkedList();
        mll.createCycleList(len);
        Node cur = mll.getHead(); //当前节点
        Node pre = null; //当前节点的上一个节点
        for (int i = 1; i < start; i++){ //定位到起始位置
            pre = null;
            cur = cur.next;
        }
        while (mll.getSize() > 1){
            for (int i = 0; i < num; i++){
                pre = cur;
                cur = cur.next;
            }
            System.out.println("杀死 "+ cur.val + " 号犯人");
            cur = mll.remove(pre, cur);
        }
        System.out.println();
        System.out.println("最后存活的是 " + cur.val +" 号犯人");
    }
}

class Node{
    public int val;
    public Node next;

    public Node(int val) {
        this.val = val;
        this.next = next;
    }
}

class MyLinkedList{
    private Node head;
    private Node tail;
    private int size;

    /**
     * 创建循环链表
     * @param len 链表中元素的个数
     */
    public void createCycleList(int len){
        if(len < 1)
            return;
        head = new Node(1);
        tail = head;
        for (int i = 1; i < len; i++){
            Node node = new Node(i+1);
            tail.next = node;
            tail = node;
        }
        tail.next = head;
        size = len;
    }

    public Node getHead(){
        return head;
    }

    public int getSize(){
        return size;
    }

    /**
     * 删除结点
     * @param pre 要删除的结点的前一个结点
     * @param cur 要删除的结点
     * @return 返回的是 cur 指向的新的引用
     */
    public Node remove(Node pre, Node cur){
        cur = cur.next;
        pre.next.next = null;
        pre.next = cur;
        size--;
        return cur;
    }
}

然后创建一个 Main 类调用 JosephusProblem 类。

/**
 * 主类
 * filename: Main.java
 */
public class Main {
    public static void main(String[] args) {
        JosephusProblem.solution(10, 4, 2);
    }
}

时间复杂度是 O ( n × m ) O(n\times m) O(n×m),空间复杂度是 O ( n ) O(n) O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值