- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章聊聊DP入门之整数拆分!由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
力扣题目链接:https://leetcode-cn.com/problems/integer-break 。
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。返回你可以获得的最大乘积.
示例 1
示例 2
说明: 你可以假设 n 不小于 2 且不大于 58.
看到这道题目,都会想拆成两个呢,还是三个呢,还是四个.... 。
我们来看一下如何使用动规来解决.
动规五部曲,分析如下:
确定dp数组(dp table)以及下标的含义 。
dp[i]:分拆数字i,可以得到的最大乘积为dp[i].
dp[i]的定义讲贯彻整个解题过程,下面哪一步想不懂了,就想想dp[i]究竟表示的是啥.
确定递推公式 。
可以想 dp[i]最大乘积是怎么得到的呢?
其实可以从1遍历j,然后有两种渠道得到dp[i]. 。
一个是j * (i - j) 直接相乘.
一个是j * dp[i - j],相当于是拆分(i - j),对这个拆分不理解的话,可以回想dp数组的定义.
j是从1开始遍历,拆分j的情况,在遍历j的过程中其实都计算过了。那么从1遍历j,比较(i - j) * j和dp[i - j] * j 取最大的。递推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j)),
也可以这么理解,j * (i - j) 是单纯的把整数拆分为两个数相乘,而j * dp[i - j]是拆分成两个以及两个以上的个数相乘.
如果定义dp[i - j] * dp[j] 也是默认将一个数强制拆成4份以及4份以上了.
所以递推公式:dp[i] = max({dp[i], (i - j) * j, dp[i - j] * j}),
那么在取最大值的时候,为什么还要比较dp[i]呢?
因为在递推公式推导的过程中,每次计算dp[i],取最大的而已.
dp的初始化 。
不少同学应该疑惑,dp[0] dp[1]应该初始化多少呢?
有的题解里会给出dp[0] = 1,dp[1] = 1的初始化,但解释比较牵强,主要还是因为这么初始化可以把题目过了.
严格从dp[i]的定义来说,dp[0] dp[1] 就不应该初始化,也就是没有意义的数值.
拆分0和拆分1的最大乘积是多少?
这是无解的.
这里我只初始化dp[2] = 1,从dp[i]的定义来说,拆分数字2,得到的最大乘积是1,这个没有任何异议.
确定遍历顺序 。
确定遍历顺序,先来看看递归公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j)),
dp[i] 是依靠 dp[i - j]的状态,所以遍历i一定是从前向后遍历,先有dp[i - j]再有dp[i].
枚举j的时候,是从1开始的。i是从3开始,这样dp[i - j]就是dp[2]正好可以通过我们初始化的数值求出来.
所以遍历顺序为:
举例推导dp数组 。
举例当n为10 的时候,dp数组里的数值,如下:
整数拆分 。
以上动规五部曲分析完毕,C++代码如下:
本题也可以用贪心,每次拆成n个3,如果剩下是4,则保留4,然后相乘,但是这个结论需要数学证明其合理性.
我没有证明,而是直接用了结论。感兴趣的同学可以自己再去研究研究数学证明哈.
给出我的C++代码如下:
时间复杂度:
空间复杂度:
本题掌握其动规的方法,就可以了,贪心的解法确实简单,但需要有数学证明,如果能自圆其说也是可以的.
其实这道题目的递推公式并不好想,而且初始化的地方也很有讲究,我在写本题的时候一开始写的代码是这样的:
在解释递推公式的时候,也可以解释通,dp[i] 就等于 拆解i - j的最大乘积 * 拆解j的最大乘积。看起来没毛病.
但是在解释初始化的时候,就发现自相矛盾了,dp[1]为什么一定是1呢?根据dp[i]的定义,dp[2]也不应该是2啊.
但如果递归公式是 dp[i] = max(dp[i], dp[i - j] * dp[j]);,就一定要这么初始化。递推公式没毛病,但初始化解释不通.
虽然代码在初始位置有一个判断if (n <= 3) return 1 * (n - 1);,保证n<=3 结果是正确的,但代码后面又要给dp[1]赋值1 和 dp[2] 赋值 2,这其实就是自相矛盾的代码,违背了dp[i]的定义.
我举这个例子,其实就说做题的严谨性,上面这个代码也可以AC,大体上一看好像也没有毛病,递推公式也说得过去,但是仅仅是恰巧过了而已.
Java 。
Python 。
Go 。
Javascript 。
原文链接:https://mp.weixin.qq.com/s/J9OiYZfrSsy0xbW-0at8cQ 。
最后此篇关于聊聊DP入门之整数拆分!的文章就讲到这里了,如果你想了解更多关于聊聊DP入门之整数拆分!的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我学过这两种DP方式,现在很迷茫。不同情况下我们如何选择?而且我发现在大多数情况下,自上而下对我来说更自然。谁能告诉我如何做出选择。 PS:这篇文章我看过older post但仍然感到困惑。需要帮忙。
我在想是否有某种通用的方法可以将自上而下的动态编程转换为自下而上的编程。 我们能否想出某种机制来提供正式的方式,通过这种方式我们可以将自上而下的 DP 转换为自下而上的 DP。 注意:我是动态规划的初
在我的 xml 中,我在 TextView 上有这个: android:textSize="18dp"(是的,我知道 dp 不适合文本,但这不是重点) 我还有其他一些以编程方式创建的 TextView
假设我正在为屏幕尺寸等于或大于 600dp 的设备开发不同的布局。我想使用 post android 3.2 资源限定符。我创建了一个名为 layout-sw600dp 的文件夹并将我的布局放在那里,
最近我在 https://leetcode.com/problems/palindrome-partitioning-ii/ 上遇到了这个问题: 给定一个字符串s,划分s使得划分的每个子串都是回文。
我已经尝试使用 admob 大约 4 个小时了,现在真的卡住了。我得到: Not enough space to show ad. Needs 320x50 dp, but only has 288
我正在尝试将可变数量的像素计算为与密度无关的像素,反之亦然。 这个公式 (px to dp): dp = (int)(px/(displayMetrics.densityDpi/160)); 不适用于
我正在从头开始创建一个 HTML 页面,并在其中动态放置值,然后将其显示在 WebView 中。 我正在尝试在 WebView(作为 HTML)中复制 ActionBar(出现在应用程序的其他 Act
我正在使用 the 4.17.37 of Bootstrap 3 Datepicker - eonasdan datepicker 我有一个正确显示的内联日期选择器,我只会使用天模式,所以我使用以下代
我正在尝试将智能横幅广告添加到我的 fragment 布局中,但我不断得到的是“没有足够的空间来展示广告。需要 320x50 dp,但只有 309x0 dp”。 这是我的 fragment 布局。
我在关于 http://developer.android.com/guide/practices/screens_support.html 的一些不幸的歧义中迷失了方向,而且我找不到澄清问题的 st
写在前面 $ DP $,是每个信息学竞赛选手所必会的算法,而 $ DP $ 中状态的转移又显得尤为关键。本文主要从状态的设计和转移入手,利用各种方法对朴素 $ DP $ 的时间复杂度和空间复杂度进行
我试图理解一种著名的正则表达式匹配 DP 算法。以防万一,人们不知道这是描述和算法。 '.' Matches any single character. '*' Matches zero or mor
注意:是的,我知道Android中还有其他处理按钮的方法,但这只是一个示例来说明我的问题(实际的按钮要复杂得多)。因此,请不要在为Android中的按钮提供其他解决方案时回信,我正在寻找PaintCo
Closed. This question needs to be more focused。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。
我正在测试 Samsung Galaxy Note 3根据文档,它是 1080 x 1920 像素(~386 ppi 像素密度)。我想弄清楚 dp 中的屏幕宽度 是多少,以便我可以正确应用并检查 ne
所以我现在完全迷路了,当用户通过Accessibility -> Font size 将字体大小时设置为Huge 时,文本大小会破坏我的 UI,所以为了快速修复 我决定将所有文本大小更改为 dp 而不
更新:我发现了我的问题。我已经为不同的分辨率定义了单独的可绘制资源,但我不知道我必须为不同的屏幕尺寸创建不同的布局。我想我应该更全面地阅读“支持多屏幕”页面。遇到此问题的任何其他人,请阅读整个页面:
阅读这篇文章(http://developer.android.com/guide/practices/screens_support.html)后,我在 xml 文件中使用 dp 单元开发了一个完整
该问题需要计算特定成本的硬币变化次数。 例如,如果我有 50, 20, 10, 5, 1 的硬币值(value),我可以形成以下成本: 5 => (5), (11111), 这是2种方式。 10 =>
我是一名优秀的程序员,十分优秀!