动态规划(Dynamic Programming, DP)

基本思想:问题的最优解如果可以由子问题的最优解推导得到,则可以先求解子问题的最优解,在构造原问题的最优解;若子问题有较多的重复出现,则可以自底向上从最终子问题向原问题逐步求解。
例子(leetcode-322):


解题思路:
对于每个金额,使用变量j遍历面值coins数组



    public int CoinChange(int[] coins, int amount)
        {
            //定义一个数组,数组下标表示金额值(从0到amount),数据存放每种金额值所需的最少硬币个数(数组长度为amount+1,从0元开始)
            //例如amount=6,下标是: 0, 1, 2, 3, 4, 5, 6 , dp[6]表示下标为6元时所需的最少硬币个数(既dp[i]是最优解)
            int[] dp = new int[amount + 1] ;
            dp[0] = 0;
            //数组1开始全部初始化为-1
            for (int i = 1; i < dp.Length; i++)
            {
                dp[i] = -1;
            }
            //首先遍历数组dp,i既表示金额值,从1开始
            for (int i = 1; i < dp.Length; i++)
            {
                //其次遍历面值集合coins
                for (int j = 0; j < coins.Length; j++)
                {
               //dp[i-coins[j]]是重点,dp[i-coins[j]]表示i金额减去每次遍历的coins[j]面额,剩下的取 min{ dp[i-coins[j]] } 最小值
               //例如i=6,面值有1,2,5,7元,首先遍历面值为1,dp[i-coins[j]]表示拿一个1元出来,剩下5元,5元最优解是dp[5],是已知的;
               //同理,再遍历2,剩dp[4];遍历5,剩dp[1],则求 min{dp[6-1],dp[6-2],dp[6-5]},其中最小的值加1就是当前金额i的最优解
                    if (i>=coins[j] && dp[i-coins[j]]!= -1 )//找出比i小的面值,且dp[i]的前面dp[比i小的]不能是-1
                    {
                        if (dp[i]==-1 || dp[i] > dp[i-coins[j]]+1)
                        {
                            dp[i] = dp[i - coins[j]]+1;
                        }
                    }
                }
            }
            return dp[amount];
        }

总结:不管子问题以后是否被用到,只要它被计算过,就将其结果填入表中(可能之后会用到子问题结果,这样就不用再重复计算了,降低时间复杂度,用空间交换时间)。这就是动态规划法的基本思路。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容