阿里一面凉了之旅

阿里一面凉了之旅

昨天才投的阿里巴巴,要我做的测评和在线编程题还没做,今天居然就打电话来面试了!真是猝不及防。在听我bb了半天项目经验,又问了点其他的 iOS 知识之后,面试官说:“我们来考察一下编程的思想吧!”。我说:“来吧!”,然后,然后我就跪了。。。

事情是这样的

面试官:“这道题很常见,你之前也可能听说过。”

我:“嗯,您说。”

面试官:“给你 1、2、5 三种面值的硬币,凑成 10,一共有多少种组合?”

我:“嗯。。。。我之前没听说过。。。。。让我想一下。。。。”

于是我在脑海中抽象了一下题目描述


现有面值分别为 $v_i$ 的 N 种硬币,需要凑成 V 元,每种硬币使用次数不限,求一共有多少种凑法?


我:“嗯。。。。最直观的想法就是暴力求解。。。”

面试官:“怎么暴力求解呢?”

我:“嗯。。。。估计要用到递归。。。”(内心OS:这样复杂度好高啊)

面试官:“怎么递归呢?”

我:“嗯。。。。每种硬币加加加,然后超过范围就退回到上一种状态。。。然后尝试下一种”(内心OS:复杂度好高!估计要用动态规划来优化下,咋搞呢)

面试官:“能说一下代码会有哪些结构吗?”

我:“*……&*@!@#)(&&)”(我也不知道我瞎说了些啥,反正答得很烂)

再又聊了一点点别的东西之后,

面试官:“好的,我会如实反映这次面试的情况。应该会在一周之内联系你,如果两周都没有联系你,那就不用再等了。”

我(带着哭腔):“好的我清楚了T^T”

挂掉电话之后

卧槽!这不就是一个动态规划吗!我咋这都没想出来!让我写一下代码!

思路:

我们需要数组 T[i][j] 表示用前 i 种硬币凑出 j 元时所有的组合数。

逐步增加 j 至 V,计算 T[i][j] 的规则如下:

遍历第 i 种硬币使用的个数,从 0(不使用)到不超过 V 的个数,记录为 k。当前硬币面值记为 v。

T[i][j] += T[i-1][j-k*v]

也就是我们考虑第 i 种硬币使用 1 个、2 个、3 个的情况,每种情况的组合数分别对应不使用这种硬币时,减去这种硬币当前凑出的面值的组合数,做一个累加就可以了。

Java实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Main {
public static void main(String[] args) throws Exception {
int[] C = {1,2,5};
System.out.println(getTotoalCombinationCount(C, 10));
}
static int getTotoalCombinationCount(int[] C, int value) {
int T[][] = new int[C.length+1][value+1];
for(int i=0; i<=C.length; i++) {
for(int j=0; j<=value; j++) {
if(j==0) {
T[i][j] = 1;
} else {
T[i][j] = 0;
}
}
}
for(int i=1; i<=C.length; i++) {
for(int j=1; j<=value; j++) {
int v = C[i-1];
for(int k=0; k*v <= j; k++) {
T[i][j] += T[i - 1][j - k*v];
}
}
}
return T[C.length][value];
}
}

需要注意的是,我们需要给二维数组 T 一个合适的初始值。当 j == 0 时,也就是需要凑成 0 元钱的时候,无论硬币有多少种,我们都有 1 种凑法:那就是不用凑。

从这个故事我们学到了

这道题确实很简单,而且又是我刚刚才学过的动态规划法。事实上我挂掉电话后用了不到半个小时就写出来了。也许是刚学过动态规划还不太熟练、也许是面试时太紧张、也许是面试过程中大脑傻掉了,反正答的很不好,还是自己太菜啊!面试官特意说两个星期内没收到后续结果就是凉了,估计是在暗示我真的凉了吧。。。我自己是感觉凉了。。

痛定思痛吧!继续努力!为找到实习而奋斗!

如果万一没凉……

虽然概率趋近于 0,但如果万一我没凉,还收到了后续面试的通知的话……我就用阿里的支付宝给贫困山区的小朋友捐 10 块钱辣条钱!


4.7 Update:

震惊!居然没凉!已捐款10元。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×