Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, …) which sum to n.
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
虽然不难,我放到这里的目的只是想说我分别用DFS,BFS,DP来解决这道题,但是DP终归是王道…
DFS
看到这道题,我想起了背包,但是没有想起背包问题肯定是dp解的,然后直接想到的就是DFS,用一个for循环,每次从后向前遍历,满足就继续遍历,跳出条件是结果为0。
具体的,我先统计小于n的平方数,然后将n,list,number放到dfs的函数中,number就是走得步数;设置一个全局变量,当结果减为0后,判断number和res中最小的,赋值给res。代码如下:
这个代码放到leetcode上,才过了48个test就超时了,48/586
举个例子:
可以看到当n=12时,就有很多种可能,而且显然后面的情况根本就不用计算,我就想给一个判断,当number大于当前res时,就不用再dfs了,因为该路径的长度肯定超出,于是想到了BFS,BFS可以计算最短路径,见下面。
BFS
BFS的核心就是使用队列,每个方向走一步,然后判断各方向是否达到了终点,到达终点就返回。
这里我用两个变量记录,一个变量表示上一步的要遍历的个数,一个变量代表当前步遍历的个数,当n=0的时候,肯定是最短路径。
这样就在leetcode上通过了,beats 35.06%
举个例子:
上面还有什么问题呢,我们注意看第二步,queue中有两个2,这样显然会重复计算,那么怎么解决呢,怎么优化呢,只能用DP了,见下面。
DP
DP的解法总是让人惊奇,用dp[i]
表示n=i的时候,需要的最小步数,有如下通项公式:
就是当n=i,然后遍历所有的可能,找出n=i的最小步数赋值给dp[i]
,代码如下:
leetcode 上betas 72.43%
举个例子:
好了,到这里就结束了,不过如果想继续研究,我们看上面的结果会发现一些数学规律,然后用这个规律也可以解决本问题,这里就不深入了。