/** * 約瑟夫問題,即單向循環(huán)鏈表問題 * @author: zhu * @date: 2020/8/30 17:57 */ public class Josepfu { public static void main(String[] args){ CircleSingleLinkedlist linkedlist = new CircleSingleLinkedlist(); linkedlist.add(5); linkedlist.showNodes(); } }
/** * 單向循環(huán)鏈表 */ class CircleSingleLinkedlist{ private Node first = null; /** * 添加節(jié)點 * @param num 需要添加的節(jié)點個數(shù) */ public void add(int num){ if (num < 1){ throw new RuntimeException("非法參數(shù)"); } Node cur = null; // 當前node for (int i = 1; i <= num; i++) { Node node = new Node(i); if (i == 1) { first = node; first.setNext(first); // next指向自己,構(gòu)成環(huán) cur = first; } else { cur.setNext(node); node.setNext(first); cur = node; } } }
/** * 遍歷 */ public void showNodes(){ if (first == null){ // 鏈表為空 return; } Node cur = first; while (true){ System.out.printf("小孩編號%d \n", cur.getNo()); if (cur.getNext() == first){ // 遍歷完畢 break; } else { cur = cur.getNext(); } } } }
/** * 節(jié)點內(nèi)部類 */ class Node{ private int no; // 編號 private Node next; // 下一個節(jié)點
public Node(int no){ this.no = no; }
public int getNo() { return no; }
public void setNo(int no) { this.no = no; }
public Node getNext() { return next; }
public void setNext(Node next) { this.next = next; } }
/** * 出圈,圈中共有n個人,從第k個開始,數(shù)m個開始出圈 * @param k * @param m * @param n */ public void get(int k, int m, int n){ if (k > n || k < 1 || first == null || m > n){ throw new IllegalArgumentException("非法參數(shù)"); } // 先找到k節(jié)點,即開始報數(shù)的節(jié)點,用cur記錄下來 Node cur = first; for (int i = 1; i < k; i++) { cur = cur.getNext(); } // 找到k的前一個節(jié)點,用pre記錄下來 Node pre = cur; while (true){ if (pre.getNext() == cur){ break; } else{ pre = pre.getNext(); } } // 出圈 while (true) { if (pre == cur) { // 只有一個節(jié)點了 System.out.printf("小孩編號%d\n", cur.getNo()); break; } // cur和pre同時移動 m-1次 for (int i = 1; i < m; i++) { cur = cur.getNext(); // 這個就是要出圈的節(jié)點 pre = pre.getNext(); // 這個是要出圈節(jié)點的前一個節(jié)點 } System.out.printf("小孩編號%d\n", cur.getNo()); cur = cur.getNext(); pre.setNext(cur); } }