1. 程式人生 > >[原創]10個人都不坐在自己座位上有多少種可能機率多大

[原創]10個人都不坐在自己座位上有多少種可能機率多大



優化後的程式碼,可以算出10個人的時候的機率,這也只能算出來10個人,11個就記憶體溢位了,可能是我設定的不夠大,但是也說明這不是一個很好的演算法。
[code=java]package com.Test;


import java.util.ArrayList;
import java.util.List;


/**
* 如果一輛車上有10個人(不包括司機和售票員),10個座位,中途休息時10個人都下車了,休息結束時,10個人回到車上。請問, 這10個人都不坐在自己座位上有多少種可能(或者求機有多大)?經理說答案是 自然數E的倒數 = 1/e

* @author peaches
* @date 2015-2-6下午10:57:21
*/
public class TestSeat {
        public static void main(String[] args) {
                for (int i = 0; i < 11; i++) {
                        long startTime = System.currentTimeMillis();
                        TestSeat seat = new TestSeat();
                        seat.peopleNum = i;
                        seat.execute();
                        System.out.println("執行時間" + (System.currentTimeMillis() - startTime));
                }
        }


        private final int num = 1;
        public int peopleNum = 5;
        private final List<String> peopleList = new ArrayList<String>();// 人
        private final List<String> seatList = new ArrayList<String>();// 座位,每個座位預設對應一個人
        private final List<List<String>> newPeopleSeatList = new ArrayList<List<String>>();// 排列組合結果


        public void execute() {
                for (int i = 1; i < peopleNum + 1; i++) {
                        String people = String.valueOf(i);
                        peopleList.add(people);
                        seatList.add(people);
                }
                // System.out.println(Arrays.toString(peopleList.toArray()));
                // System.out.println(Arrays.toString(seatList.toArray()));
                generateList(0);
                valid();
        }


        /**
         * 驗證排列組合,只保留所有的都不在原來座位上的。刪除任何存在“在自己座位上的排列組合”
         */
        private void valid() {
                List<List<String>> resultPeopleSeatList = new ArrayList<List<String>>();// 排列組合結果
                int count = newPeopleSeatList.size();// 所有排列總數
                System.out.println("總人數:" + peopleList.size());
                for (int i = newPeopleSeatList.size() - 1; i > 0; i--) {
                        List<String> tempList = newPeopleSeatList.get(i);
                        if (validList(tempList)) {
                                resultPeopleSeatList.add(newPeopleSeatList.get(i));
                        }
                        newPeopleSeatList.remove(i);
                }
                // System.out.println(num++ + ":" +
                // Arrays.toString(newPeopleSeatList.toArray()));
                System.out.println("所有人均不在自己座位上的可能數量:" + resultPeopleSeatList.size());
                System.out.println("所有人均不在自己座位上的可能機率:" + String.format("%.3f%%", resultPeopleSeatList.size() * 1.0 / count * 100));
                System.out.println("----------------------------------------------------------------");
        }


        private boolean validList(List newList) {
                for (int i = 0; i < seatList.size(); i++) {
                        if (newList.get(i).equals(seatList.get(i))) {
                                return false;
                        }
                }
                return true;
        }


        /**
         * 生成所有的可能的組合
         * 
         * 程式的主要思路是: 1.把第1個數換到最前面來(本來就在最前面),準備列印1xx,再對後兩個數2和3做全排列。 2.把第2個數換到最前面來,準備列印2xx,再對後兩個數1和3做全排列。 3.把第3個數換到最前面來,準備列印3xx,再對後兩個數1和2做全排列。
         * 
         * 可見這是一個遞迴的過程,把對整個序列做全排列的問題歸結為對它的子序列做全排列的問題,注意我沒有描述Base Case怎麼處理,你需要自己想。 你的程式要具有通用性,如果改變了N和陣列a的定義(比如改成4個數的陣列),其它程式碼不需要修改就可以做4個數的全排列(共24種排列)。
         * 
         * 完成了上述要求之後再考慮第二個問題:如果再定義一個常量M表示從N個數中取幾個數做排列(N==M時表示全排列),原來的程式應該怎麼改?
         * 
         * 最後再考慮第三個問題:如果要求從N個數中取M個數做組合而不是做排列,就不能用原來的遞迴過程了,想想組合的遞迴過程應該怎麼描述,程式設計實現它。
         */
        public void generateList(int k) {
                if (k == peopleNum) {
                        List<String> tempList = new ArrayList<String>();
                        tempList.addAll(peopleList);
                        newPeopleSeatList.add(tempList);
                        // System.out.println(num++ + ":" +
                        // Arrays.toString(newPeopleSeatList.toArray()));
                } else {
                        for (int i = k; i < peopleNum; ++i) {
                                swap(i, k);// 交換字首
                                generateList(k + 1);// 遞迴
                                swap(i, k);// 將字首換回來,繼續做前一次排列
                        }
                }
        }


        public void swap(int i, int offset) {
                String tempI = peopleList.get(i);
                String tempOffset = peopleList.get(offset);
                peopleList.remove(i);
                peopleList.add(i, tempOffset);
                peopleList.remove(offset);
                peopleList.add(offset, tempI);
        }
}[/code]


執行結果


總人數:0
所有人均不在自己座位上的可能數量:0
所有人均不在自己座位上的可能機率:0.000%
----------------------------------------------------------------
執行時間99
總人數:1
所有人均不在自己座位上的可能數量:0
所有人均不在自己座位上的可能機率:0.000%
----------------------------------------------------------------
執行時間0
總人數:2
所有人均不在自己座位上的可能數量:1
所有人均不在自己座位上的可能機率:50.000%
----------------------------------------------------------------
執行時間1
總人數:3
所有人均不在自己座位上的可能數量:2
所有人均不在自己座位上的可能機率:33.333%
----------------------------------------------------------------
執行時間8
總人數:4
所有人均不在自己座位上的可能數量:9
所有人均不在自己座位上的可能機率:37.500%
----------------------------------------------------------------
執行時間0
總人數:5
所有人均不在自己座位上的可能數量:44
所有人均不在自己座位上的可能機率:36.667%
----------------------------------------------------------------
執行時間3
總人數:6
所有人均不在自己座位上的可能數量:265
所有人均不在自己座位上的可能機率:36.806%
----------------------------------------------------------------
執行時間15
總人數:7
所有人均不在自己座位上的可能數量:1854
所有人均不在自己座位上的可能機率:36.786%
----------------------------------------------------------------
執行時間92
總人數:8
所有人均不在自己座位上的可能數量:14833
所有人均不在自己座位上的可能機率:36.788%
----------------------------------------------------------------
執行時間253
總人數:9
所有人均不在自己座位上的可能數量:133496
所有人均不在自己座位上的可能機率:36.788%
----------------------------------------------------------------
執行時間1175
總人數:10
所有人均不在自己座位上的可能數量:1334961
所有人均不在自己座位上的可能機率:36.788%
----------------------------------------------------------------
執行時間5210


一樓臺的,10個人,執行了40分鐘沒有結果。現在的,平均執行時間5s左右,根據電腦不同會有不同。