菜鸟刷题记!一道阿里算法面试题 ,来挑战不!

在浩瀚无垠的东方玄域有无数的大大小小的门派,分布在丛山峻岭之间。其中位列顶尖有A门派,T门派,B门派,H门派,M门派,Z门派这6大势力最强,受众最广。每年都会通过笔试面试,挑选码农入门派内修炼。而码农在修炼的过程中有三大神器必看:

  • 写代码无论是遇到任何问题上,只要上Stackoveflow都能查到答案;

  • 查看源码,无论是复杂的框架还是小的脚本,都可以在GitHub上搜索查到;

  • 学会精妙的算法尤其是面试大门派之前,必刷LeetCode ;

小编周末在家,也开始静心的修炼起来,今天来刷一道在LeetCode上非常有名的题目CoinChange,据说这道面试题有师兄在阿里被面过,来一起挑战一下

1.题目:零钱兑换

给你不同面额的硬币coins和一个总金额amount。需要你来写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1

示例:

输入: coins = [1, 2, 5], amount = 11

输出: 3 

解释: 11 = 5 + 5 + 1

示例:

输入: coins = [2], amount = 3

输出: -1 

2.菜鸟解法:暴力求解

如果不太动脑子不考虑效率的话,抱着不管三七二十一先做出来再说的话,肯定是暴力遍历比较容易想到。其实就是一个很简单的数学公式11=x1* 1+x2*2+x3*5,我们直接三层循环即可。

面值为1的钱币最大11张,x1的搜索空间为0-11

面值为2的钱币最大5张,x2的搜索空间为0-5

面值为5的钱币最大2张,x3的搜索空间为0-2

1).第一步算出每一张币种的最大张数

如果我们的输入的coins=[1,2,5],target =11 ,那么每一种币种的最大张数为11,5,2

2).进行空间搜索,凑到面值为11的组合

通过暴力的循环迭代,把凑到的钱币为11的组合用yield记录下来。

得到的组合示例为:

(4, [0, 3, 1])  

4是使用钱币的张数,0表示0张1元面,3表示3张2元面,1表示1张5元面值

(3, [1, 0, 2])  

3是使用钱币的张数,1表示1张1元面,0表示0张2元面,2表示1张5元面值

3).对组合的结果进行排序

4).运行看一下结果

最后的结果就是{1: 1, 2: 0, 5: 2} ,最少用3张:1元面值*1,5元面值*2

3.优化:进阶解法

上面的解法平铺直叙,但是很明显有致命的缺陷,因为c1,c2,c3都是写死的,这样的话肯定不行,如果我们的币种的数目变化的不是3种,那上面的代码就直接挂了。

因为我们代码里写死了循环3层,其实每一个币种的面值也不一定是1,2,5,所以我们需要换一个思路来处理,代码优化如下:

三个币种【1,2,5】,每一种币种若要凑11元的最多使用张数为【11,5,2】,那么对于每一个面值的来说组合为:

  • 1元:[(0,1),(1,1),(2,1),(3,1)...(11,1)] 即为0张1元,1张1元,2张1元,3张1元

  • 2元:  [(0,2),(1,2),(2,2),(3,2)...(5,2)]即为0张2元,1张2元,2张2元,3张2元

  • 5元:[(0,5),(1,5),(2,5)]即为0张5元,1张5元,2张5元

然后我们把所有的币种的组合进行全排列即可

我们先得出币种和最大的张数的一个mapping,就是[(11, 1), (5, 2), (2, 5)]

接着进行把币种的单一面值的组合都列出来,就是:

[[0, 1], [1, 1], ... [11, 1], [0, 2], [1, 2],... [5, 2], [0, 5], [1, 5], [2, 5]]

最后用itertools里面的permutations进行全排列,剩下的其实就是对全排列的组合进行排序,就很简单了。

4. 王者:大神解法

上面的解法时间复杂度很高,而且效率很低,完全没有美感可言,非常简单粗暴。在真正的生成环境是不能这样使用的,很明显我们需要另辟蹊径。这个问题是一个很明显的动态规划问题。

动态规划算是算法里面比较难理解的一个概念,每个动态规划都是从网格开始。

对于面值1元,2元,5元,要凑11元,我们从0开始最大使用11张。

每一个等级的钱数我们通过网格画出使用最少的钱数,那么这个问题就分解为1+10: 寻找满足1元使用最少的钱数 和10元使用最少的钱数

2+9: 寻找满足2元使用的最少的钱数,寻找满足9使用最少的钱数

3+8: 寻找满足3元使用的最少的钱数,寻找满足8元使用最少的钱数

以此类推。。。

设计一个dp容器,进行存储每一个面值需要的最少的张数,一开始设置为正无穷大;

用2层循环去搜索这个网格,把每一个面值的使用的最少张数存进网格

我们输入几个测试用例看一下结果:

测试用例全部通过,懂点算法还是很有用点,尤其是面试招聘,行走江湖还是需要几把刷子呢!有的同学说面试的时候严格的像造火箭,招进去干活的活就是每天拧螺丝

确实现实很骨干,但是拧螺丝也得有本书先混进大厂才行啊。好了,不啰嗦啦,小伙伴赶紧Python学起来!

end

有热门推荐????

1. 超全Python IDE武器库大总结,优缺点一目了然!

2. Python 30道高频面试题及详细解答

3. 精华技巧,学会这几招可以假装是Python高手

4. 哇!用Python读取CVS文件竟然有5招,据说90%的人只会2招

菜鸟编程大本营,现已正式上线!
接下来我们将会在该公众号上,为大家分享优质编程语言里趣味的干货,通俗易懂的实战案例,经验分享,让菜鸟也爱上编程。
点这里,领取新手福利
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值