n個(gè)小孩子手拉手圍成一個(gè)圈,編號(hào)為k(1 <= k <= n )的人從1開始報(bào)數(shù),報(bào)到m的那個(gè)人出列,它的下一位又從1開始報(bào)數(shù),報(bào)到m的又出列……依此類推,直到所有人都出列,由此產(chǎn)生一個(gè)出隊(duì)編號(hào)的序列。
/** * 約瑟夫問題,即單向循環(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é)點(diǎn) * @param num 需要添加的節(jié)點(diǎn)個(gè)數(shù) */ public void add(int num){ if (num < 1){ throw new RuntimeException("非法參數(shù)"); } Node cur = null; // 當(dāng)前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("小孩編號(hào)%d \n", cur.getNo()); if (cur.getNext() == first){ // 遍歷完畢 break; } else { cur = cur.getNext(); } } } }
/** * 節(jié)點(diǎn)內(nèi)部類 */ class Node{ private int no; // 編號(hào) private Node next; // 下一個(gè)節(jié)點(diǎn)
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個(gè)人,從第k個(gè)開始,數(shù)m個(gè)開始出圈 * @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é)點(diǎn),即開始報(bào)數(shù)的節(jié)點(diǎn),用cur記錄下來 Node cur = first; for (int i = 1; i < k; i++) { cur = cur.getNext(); } // 找到k的前一個(gè)節(jié)點(diǎn),用pre記錄下來 Node pre = cur; while (true){ if (pre.getNext() == cur){ break; } else{ pre = pre.getNext(); } } // 出圈 while (true) { if (pre == cur) { // 只有一個(gè)節(jié)點(diǎn)了 System.out.printf("小孩編號(hào)%d\n", cur.getNo()); break; } // cur和pre同時(shí)移動(dòng) m-1次 for (int i = 1; i < m; i++) { cur = cur.getNext(); // 這個(gè)就是要出圈的節(jié)點(diǎn) pre = pre.getNext(); // 這個(gè)是要出圈節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn) } System.out.printf("小孩編號(hào)%d\n", cur.getNo()); cur = cur.getNext(); pre.setNext(cur); } }