丟手帕問題 (約瑟夫問題)Java實現

問題:數組

丟手帕遊戲是約瑟夫問題的一個變種,遊戲很簡單,N個小孩圍成一個圈,標號爲1到N,從編號爲m的小孩開始報數,報到第L個小孩退出遊戲,而後下一個小孩繼續從1開始報數,數到第L個小孩退出遊戲,如此循環,直到剩下最後一個小孩是勝利者.數據結構

 

使用環形鏈表方式解決問題:oop

代碼以下:ui

/**
 * 描述:
 * @做者:niexiaohui
 * @建立時間:2016年12月27日
 * @修改記錄:
 */
public class Test {
    public static void main(String[] args) {
        long starttime=System.currentTimeMillis();
        CircleLinkList game=new CircleLinkList(10000, 99, 533);
        long endtime=System.currentTimeMillis();
        game.play();
        long time2=System.currentTimeMillis();
        System.out.println("建立鏈表用了"+(endtime-starttime)/1000.0+"秒");
        System.out.println("玩遊戲共用了"+(time2-starttime)/1000.0+"秒");
    }
}

class Child{
    protected int no;
    protected Child nextChild;
    public Child(int no){
        this.no=no;
    }
}

class CircleLinkList{
    /**
     * 參與遊戲人數
     */
    private int playBoys;
    /**
     * 從第幾個開始數
     */
    private int startIndex;
    /**
     * 數幾個小孩退出
     */
    private int countNum;
    //首個小孩
    private Child firstChild;
    //標識當前小孩
    private Child temp;
    /**
     * 
     * @param playBoys 參與遊戲人數
     * @param startIndex 從第幾個開始數
     * @param countNum 數幾個小孩退出
     */
    public CircleLinkList(int playBoys, int startIndex, int countNum) {
        super();
        this.playBoys = playBoys;
        this.startIndex = startIndex;
        this.countNum = countNum;
        createList();
    }
    /**
     * 建立循環鏈表
     */
    private void createList() {
        for (int i = 1; i <=playBoys; i++) {
            if (i==1) {//第一個小孩
                Child child=new Child(i);
                this.firstChild=child;
                this.temp=child;
            }else if (i==playBoys) {//最後一個小孩
                Child child=new Child(i);
                this.temp.nextChild=child;
                this.temp=child;
                this.temp.nextChild=this.firstChild;//最後一個小孩的下一個小孩指向第一個小孩
            }else {
                Child child=new Child(i);
                this.temp.nextChild=child;
                this.temp=child;
            }
        }
    }
    
    /**
     * 玩遊戲
     */
    public void play(){
        temp=firstChild;
        //先找到從第幾個小孩開始數
        for (int i = 1; i < startIndex; i++) {
            temp=temp.nextChild;
        }
        System.out.println("遊戲開始,從第"+temp.no+"個小孩開始數,數到第"+this.countNum+"個小孩退出遊戲");
        while (this.playBoys>1) {
            //找到要退出遊戲的前一個小孩
            for (int i = 1; i < countNum-1; i++) {
                temp=temp.nextChild;
            }
            //當前temp是要退出的前一個小孩
            Child leaveChild=temp.nextChild;//要退出的小孩
            System.out.println("當前退出的小孩編號爲:" +leaveChild.no);
            temp.nextChild=leaveChild.nextChild;
            if (leaveChild.no==firstChild.no) {//若是要退出的小孩是第一個小孩,則將第一個小孩重置爲退出小孩的下一個小孩
                this.firstChild=leaveChild.nextChild;
            }
            temp=temp.nextChild;
            this.playBoys--;//玩遊戲人數少一個
        }
        System.out.println("最後剩下的小孩是:"+ temp.no);
    }
}

代碼雖然很多,可是並不難懂,有過一點數據結構基礎的仍是很容易理解的.this

 

使用數組方式解決問題:spa

 

代碼以下:code

 

/**
 * 描述:
 * 
 * @做者:niexiaohui
 * @建立時間:2017年1月11日
 * @修改記錄:
 */
public class Test4 {

    public static void main(String[] args) throws InterruptedException {
        long starttime = System.currentTimeMillis();
        int childrens=10000;//玩遊戲的小孩總數
        int countNum=533;//數第幾個小孩退出遊戲
        int startNum=99;//開始從第幾我的開始數
        int count=1;//計數器
        int [] arrays=new int[childrens];
        for (int i = 0; i < arrays.length; i++) {//爲數組初始化值
            arrays[i]=1;
        }
        loop:while(true){
            for (int i = 0; i < arrays.length; i++) {
                if (i<startNum-1) {//第一次循環找到從第幾個小孩開始數數
                    continue;
                }
                startNum=0;//開始後將startNum清零
                if (arrays[i]!=0) {//值爲0的表示已經退出遊戲
                    if (count%countNum==0) {//數到的小孩退出遊戲
                        if (childrens==1) {
                            System.out.println("遊戲勝利的小孩編號爲:"+(i+1));
                            break loop;
                        }
                        arrays[i]=0;//退出遊戲的小孩值設爲0
                        count=0;//計數器清零,從新計數
                        childrens--;//玩遊戲的人數減一
                        System.out.println("編號爲"+(i+1)+"的小孩退出遊戲");
                    }
                    count++;
                }
            }
        }
        long time2 = System.currentTimeMillis();
        System.out.println("玩遊戲共用了" + (time2 - starttime)/1000.0 + "秒");
    }

    

}

 

 

用數組方式解決問題代碼少了不少,效率上,我大體比較了下,隨着數到第L個小孩退出遊戲,即L的增大,鏈表的速度會提高,相反數組會降低,若是L值很小的話,數組的效率是高於鏈表的效率的.blog

相關文章
相關標籤/搜索