創新工廠面試題詳解:共打了多少魚 -- 正解 遞歸求解法

     今天看了一篇博文創新工場面試題詳解題目abcde五人打漁,打完睡覺,a先醒來,扔掉1條魚,把剩下的均分成5分,拿一份走了;b再醒來,也扔掉1條,把剩下的均分成5份,拿一份走了;然後cde都按上面的方法取魚。問他們一共打了多少條魚?

      許多小朋友都參與其中,挺有意思,我看了一下參與者的答案,發現大多都是採用循環遍歷的方法,雖然能得到解,但不是正確的解題思路,這道題有簡單的數學解: X = 5^5 - (5-1);

   該題目可以推廣到M個人,假設第一個人分魚前有X1條魚,第二個人分魚前有X2條魚.....第M個人分魚前有Xm條魚, 如果把魚的數量增加M-1條,每個人都可以均分後拿掉自己的一份(不用再扔掉一條了),這樣你可以導出:

       X1 = M^M * Xm+1 / (M-1)^(M-1); 

    而 Xm+1 / (M-1)^(M-1) 的最小整數值爲1,因此 X1 = M^M 了,再減去添加的M-1條,就得到了答案。 

      但作爲編程題是在考你是否會使用遞歸算法.

       根據題意可以得出如下公式:

        X1- (X1-1)/M - 1 =X導出X1 = (M*X2+M-1)/(M-1), 進一步可以推到出Xn = (M*Xn-1+M-1)/(M-1)。

     跟據題意還可以知道,最後一個人分完後,魚的數量是可以被M-1個人均分的 ,即Xm+1= (M-1)*k,  k=1,2,3....爲>0的整數。這樣對於確定的M和k,Xm+1的值就是已知的,這樣就可以用遞歸法求解該題了。

     這樣的解題效率是高的,對於M=5的情況,僅需255次循環就可以得到解 X1=3121.

     爲了增加趣味性,本程序在得到解後,將X1 ~ Xm  都輸出出來了。

     具體參見下面的代碼,該程序採用遞歸算法,不太好理解,請大家認真閱讀,遞歸程序是程序員的基本功啊。

     不過這都是具體小玩意,小遊戲而已,要想成爲優秀的軟件工作者,還是要多學習編碼是設計方面的理論:參見http://blog.csdn.net/xabcdjon/article/details/6707050   和http://blog.csdn.net/xabcdjon/article/details/6823653

public class DisFish {
	static int M = 5;  //人的個數
	static int N = 2;  //希望得到幾個結果
	static int result[] = new  int[M];
	public static void main(String[] args) throws Exception

	{		
		int n = 0;
		int k = 1;
		while (n < N) {
			int x1 = calculateX(2,k);   //x1 = f(x2) x1是x2的函數。
			if (x1>0) {
				n++;
				result[0]= x1;
				outRes(k);
			}
			k++;
		}
	}	
	/**
	 * 遞歸求解 Xm-1 =  (M*Xm+M-1)/(M-1) 
	 * @param m
	 * @param k  試算的正整數
	 * @return  返回-1 表示整數k試算失敗,因爲剩餘的數量不能被M-1個人均分
	 */
	static int calculateX (int m,int k) {
		int xm = -1;
		if (m>M) {
			int x = (M-1)*k;
			xm = M*x / (M-1) + 1;
			return xm;
		}
		int xplus = calculateX(m+1,k);  //遞歸求解Xm+1
		if (xplus<0) return -1;
		int r = M*xplus%(M-1);
		if (r!=0) return -1;      //剩餘的數量不能被M-1個人均分
		xm = M*xplus / (M-1) + 1;
		result[m-1] = xm;         //記錄Xm 
		return xm;
	}
	
	static void outRes(int k){
		System.out.println(" k="+k);
		for (int i = 0; i < result.length; i++) {
			int p = i+1;
			System.out.print("X"+p+"="+result[i]+" ");
		}
		System.out.println();
	}
}


 你也可以試着採用增加M-1條魚後的遞歸公式進行編程求解,加深一下對遞歸算法的掌握。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章