Java 約瑟夫環問題解決方案

1、問題描述

約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知n個人(以編號1,2,3…n分別表示)圍坐在一張圓桌周圍。從編號爲k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。通常解決這類問題時我們把編號從0~n-1,最後結果+1即爲原問題的解。–百度百科

2、解決方案

  
  這裏主要使用了LinkedList來存儲所有人的信息,假設有n個人,編號爲0-n-1,默認是從編號爲0的第一個人開始報數,每次從List中取出第一個元素來,如果此時報的數是淘汰數字的整數倍,則將該元素淘汰掉,否則放到List的末尾中,循環執行這個過程直到List中的人數與要求結束的人數相等爲止,返回List中的編號組成的數組即可。

3、代碼實例


import java.util.LinkedList;
import java.util.Scanner;

/**
 * 約瑟夫環問題,輸入總人數,每個人的編號從0開始,輸入一個淘汰數字,當報數的人報的數爲淘汰數字的整數倍數該人淘汰,後面的人繼續報數(或從新報數是一樣的)
 */
public class JosephDemo {

    private LinkedList<Integer> perList;
    private int start;
    private int scale;
    private int end;

    /**
     * @param num
     *            總人數,每個人的編號是從0開始的
     * @param start
     *            起始報數
     * @param scale
     *            報數爲scale的整數倍時淘汰一個人,比如scale爲3,則報數爲3、6...的人會淘汰
     * @param end
     *            結束時剩餘的人數
     */
    public JosephDemo(int num, int start, int scale, int end) {
        perList = new LinkedList<Integer>();
        for (int i = 0; i < num; i++) {
            perList.add(i);
        }
        this.start = start;
        this.scale = scale;
        this.end = end;
    }

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        System.out.print("請輸入總人數,大於0的整數:");
        int num = scanner.nextInt();

        System.out.print("請輸入淘汰數字,大於0的整數:");
        int scale = scanner.nextInt();

        System.out.print("請輸入起始報數的編號,大於等於0的整數:");
        int start = scanner.nextInt();

        System.out.print("請輸入結束時剩餘的人數,大於0的整數:");
        int end = scanner.nextInt();

        long l = System.currentTimeMillis();
        JosephDemo yd = new JosephDemo(num, start, scale, end);
        Integer[] index = yd.findEnd();
        System.out.print("剩下的編號爲:");
        for (int i = 0; i < index.length; i++) {
            System.out.println(index[i] + 1);
        }
        System.out.println("耗時:" + (System.currentTimeMillis() - l));
    }

    /**
     * 找到剩下輸入的結束人數時的所有編號
     * 
     * @return
     */
    private Integer[] findEnd() {
        int lastNum = perList.size();
        int _start = this.start;
        while (lastNum != this.end) {
            Integer head = perList.pop();
            if (_start % scale == 0) {
                lastNum--;
            } else {
                perList.addLast(head);
            }
            _start++;
        }
        Integer[] result = perList.toArray(new Integer[0]);
        return result;
    }
}

執行的結果:

請輸入總人數,大於0的整數:1000
請輸入淘汰數字,大於0的整數:13
請輸入起始報數的編號,大於等於0的整數:1
請輸入結束時剩餘的人數,大於0的整數:1
剩下的編號爲:396
耗時:16
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章