创新工厂面试题详解:共打了多少鱼 -- 正解 递归求解法

今天看了一篇博文创新工场面试题详解题目: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 =X2导出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/6707050http://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条鱼后的递归公式进行编程求解,加深一下对递归算法的掌握。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值