算法笔记 -- 约瑟夫环问题Java两种写法
// 问题背景: 10人围成圈,从1-3数数,数到3退出,求最后推出的人?
public static void main(String[] args){ // 约瑟夫环问题 // 法一:使用单向环连表 Linked head = initLinked(); Linked last = doGame(head); System.out.println(last.val); System.out.println("----------------"); // 法二:使用数组 int[][] arr = {{1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {8, 1}, {9, 1}, {10, 1}}; System.out.println(doGame(arr)); } private static int doGame(int[][] arr) { int idx = 1; for (;;) { if (arr.length == 1) return arr[0][0]; int retCnt = arr.length; for (int i = 0; i < arr.length; i ++) { if (idx % 3 == 0) { retCnt --; arr[i][1] = 0; System.out.println(idx + " | " + arr[i][0]); } idx ++; } int[][] newArr = new int[retCnt][]; int newIdx = 0; for (int[] a : arr) { if (a[1] != 0) { newArr[newIdx ++] = a; } } arr = newArr; } } private static Linked doGame(Linked head) { Linked prev = head; int idx = 1; for (;;) { if (prev.next == prev) return prev; if (idx % 3 == 0) { System.out.println(idx + " | " + head.val); Linked next = head.next; prev.next = next; head.next = null; head = next; } else { prev = head; head = head.next; } idx ++; } } private static Linked initLinked() { Linked head = new Linked(1), cur = head; for (int i = 2; i < 11; i ++) { Linked newCur = new Linked(i); cur.next = newCur; cur = newCur; } cur.next = head; return head; } static class Linked { int val; Linked next; public Linked(int val) { this.val = val; } }