实现约瑟夫环形链表

题目

41个人排成一个圆圈,由第1个人 开始报数,每报数到第3人,该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。约瑟夫与朋友在第16与第31个位置,于是活了下来。请用单向环形链表描述该结构并呈现整个自杀过程。

设计

  • 首先要设计一个节点模型
     class Node {
        int value;
        Node next;
        Node(int value) {
            this.value = value;
        }
     }
  • 遍历并用 last 节点做成一个单向线性的链表,之后将自身的初始节点指向last.next 节点,扣成一个环
    Node head = new Node(1);
    Node last = head;
    /** 一条单链数据 */
   
     for (int i = 2; i <= n; i++) {
            last = (last.next = new Node(i));
    }

   /**
   回调指向,形成环形链,可用如下代码做环形链表是否形成的测试
    System.out.println(last.next.next.value);
   */
    last.next = head;
  • 遍历每个报数到m(m=3)的节点,并重组链表
    for (int i = 1; i < m; i++) {
        last = last.next; //6
    }
    /**首先以总人数3为例,再以6为例推测这段代码,以及结合for循环就很好理解了*/
     last.next = last.next.next; //3、4、5
  • 整个自杀链表遍历的结束条件
    /**
    以总人数 3 为例 last.next 经过遍历为3时赋值给 last ,
    此时 last==last.next 是成立的,即可跳出while循环
    */
    while (last != last.next) {
        for (int i = 1; i < m; i++) {
           last = last.next;
        }
        last.next = last.next.next;
  }

实现

import org.junit.Test;
import static java.lang.System.out;

/**
 * @author lorem
 */
public class NodeNodeNext {
    class Node {
        int value;
        Node next;
        Node(int value) {
            this.value = value;
        }
    }

    @Test
    public void test() {
        winner(41, 3);
    }

    void winner(int n, int m) {
        Node head = new Node(1);
        Node last = head;
        /** 一条单链数据 */
        for (int i = 2; i <= n; i++) {
            last = (last.next = new Node(i));
        }
        /**回调指向,形成环形链*/
        last.next = head;
        out.println("依次死亡的序号:");
        while (last.value != last.next.value) {
            for (int i = 1; i < m; i++) {
                last = last.next;
            }
            out.print(last.next.value + " ");
            last.next = last.next.next;
        }
        out.println("\n" + "最后存活的序号:");
        out.printf("%d", last.value);
    }
}
posted @ 2018-09-23 20:13 lorem 阅读(...) 评论(...) 编辑 收藏