作为一名程序员,遇到这样的情况,真的让人心情复杂。裁员不给交接时间,直接让你走人,心里难受不说,工作上的东西也没法好好交接。
明明有些项目和代码还没完全梳理清楚,结果人家就直接让你走了。
然后问题来了,离职后,前同事和领导还开始反复给你发微信,电话,甚至叫你拉群、开会讨论问题。就挺。。。关我啥事~
我觉得,面对这种情况,直接拉黑倒是一个极端的解决办法,但我更建议做个平衡点的处理:如果真是自己能解决的小问题,随便帮忙一下,大家也都理解,但如果是反复不断、无理要求,那就要学会说不了。
毕竟,自己已经跳出那个坑了,不能再让别人拉着你往回走。
算法题:零钱兑换
今天我们来聊一个经典的算法问题:零钱兑换。
问题的背景是这样的:
给定不同面额的硬币和一个总金额,找出能够凑成这个金额的最小硬币数。你可以认为每个硬币的数量是无限的。说白了,就是给你若干面额的硬币,要求你用尽量少的硬币数去凑出一个指定的金额。
想象一下,如果你有3种硬币,分别是1元、2元和5元,目标金额是11元。用最少的硬币数量凑出11元应该是怎样的呢?答案显然是:1元×1 + 2元×1 + 5元×2,共使用3个硬币。
那么,问题来了,这个问题怎么用程序来解决?我们可以使用动态规划(DP)来解决它。首先,动态规划是一个非常典型的分治思想的应用,特别适合用来解决“最优解”类型的问题。
接下来,直接看代码实现吧:
def coinChange(coins, amount):
# 初始化dp数组,dp[i]表示凑成金额i所需的最小硬币数
dp = [float('inf')] * (amount + 1)
dp[0] = 0 # 凑成金额0不需要硬币,硬币数是0
# 遍历每个金额
for i in range(1, amount + 1):
for coin in coins:
if i - coin >= 0:
dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
这个代码的核心思想是,定义一个dp
数组,dp[i]
表示凑成金额i
所需的最小硬币数。然后,我们通过每种硬币面额来更新dp
数组。如果用某种硬币能凑出更少的硬币数,就更新dp[i]
。
解释一下这个代码的工作原理:
-
初始化
dp
数组,大小是amount + 1
,因为金额从0到amount
都有可能。初始值设置为无穷大,表示无法用某些硬币组合成这个金额。 -
dp[0]
设为0,因为凑成金额0不需要任何硬币。 -
然后,遍历每个金额
i
,对于每种硬币面额coin
,判断当前金额i
能否通过减去硬币coin
得到一个已经计算过的金额。若是,可以更新dp[i]
的值为更小的硬币数。 -
最后返回
dp[amount]
,如果它依然是无穷大,说明无法凑出该金额,返回-1
。
举个例子:假设coins = [1, 2, 5]
,amount = 11
,执行完上面的代码后,dp[11]
的值会是3,表示最少需要3个硬币(如:5+5+1)。
动态规划的时间复杂度分析:
这个算法的时间复杂度是O(amount * len(coins))
,因为对于每一个金额,我们都要遍历一次所有的硬币面额。如果金额amount
很大,硬币面额很多,可能会导致计算量稍大,但总体来说这个算法效率还算可以。
通过这个例子,我们还可以看到,使用动态规划需要有一个很清晰的“状态”定义,这样才能通过状态转移公式一步步逼近目标。而且,像我这种“懒程序员”在编程时,越是能找到有效的优化路径,就越能提高自己的效率。动态规划正是通过记录中间结果避免了重复计算,简化了问题。
总之,这道零钱兑换的问题,看似简单,实则包含了很多编程中的精髓。它让我更加理解了“动态规划”这个思想背后的力量——把问题分解,再把小问题逐步解决,最终达到最优解。
标签:硬币,拉黑,微信,金额,amount,群拉会,面额,coin,dp From: https://blog.csdn.net/2401_88796361/article/details/144135541