环形链表解决约瑟夫环问题(java简单实现)

467 阅读1分钟

约瑟夫环是个很经典的问题,其中一个简单的实现方式使用环形链表。在这篇文章中,将用环形链表简单的解决这个问题。

我们首先来看一个环形的链表结构

image.png

在这个结构中我们定义了一个并不存储数据的虚拟头结点。然后把链表收尾相连,这样就形成了一个环形的循环结构。

构建环形链表很简单,我们先定义一个链表的基本结构

class Node {
    int data;
    Node next;

    public Node() {
    }

    public Node(int data) {
        this.data = data;
    }
}

然后构造链表

        Node head = new Node();
        Node cur = head;
        //构造链表
        for (int i = 1; i <= n; i++) {
            Node node = new Node(i);
            cur.next = node;
            cur = node;
        }
        cur.next = head.next; //首位连接形成环形链表
        Node pre = head.next;

现在就完成了一个循环链表了

然后我们就要遍历链表删除节点例如我们数到k就删除节点就会有如下代码

    while (pre.next != pre) {
        for (int i = 1; i < k - 1; i++) {
            pre = pre.next;
        }
        System.out.print(pre.next.data + "->");
        pre.next = pre.next.next;
        pre = pre.next;
    }

我们假设k是3这也是约瑟夫的问题中的例子,那么for循环中我们循环了1次。此时pre指向要被删除的节点的前一个节点。然后执行我们的删除逻辑就可以了。

当满足while 的终止条件时,整个循环链表也只剩下一个节点。这就是我们最后剩下的节点。

整体代码如下:

public class yuesefuhuan {
    public static void main(String[] args) {
        count(41, 3);
    }

    public static void count(int n, int k) {
        Node head = new Node();
        Node cur = head;
        //构造链表
        for (int i = 1; i <= n; i++) {
            Node node = new Node(i);
            cur.next = node;
            cur = node;
        }
        cur.next = head.next; //首位连接形成环形链表
        Node pre = head.next;
        //开始遍历节点
        while (pre.next != pre) {
            for (int i = 1; i < k - 1; i++) {
                pre = pre.next;
            }
            System.out.print(pre.next.data + "->");
            pre.next = pre.next.next;
            pre = pre.next;
        }
        System.out.println("zuihou:" + pre.data);


    }

}

class Node {
    int data;
    Node next;

    public Node() {
    }

    public Node(int data) {
        this.data = data;
    }
}

执行以下结果为: 3->6->9->12->15->18->21->24->27->30->33->36->39->1->5->10->14->19->23->28->32->37->41->7->13->20->26->34->40->8->17->29->38->11->25->2->22->4->35->16->zuihou:31

符合约瑟夫问题的例子。