题目

Initially on a notepad only one character 'A' is present. You can perform two operations on this notepad for each step:

  1. Copy All: You can copy all the characters present on the notepad (partial copy is not allowed).
  2. Paste: You can paste the characters which are copied last time.

Given a number n. You have to get exactly n 'A' on the notepad by performing the minimum number of steps permitted. Output the minimum number of steps to get n 'A'.

Example 1:

Input: 3
Output: 3
Explanation:
Intitally, we have one character 'A'.
In step 1, we use Copy All operation.
In step 2, we use Paste operation to get 'AA'.
In step 3, we use Paste operation to get 'AAA'.

Note:

  1. The n will be in the range [1, 1000].

思路

1、O(n^2)的动态规划:

我们定义dp[i][j]表示在粘贴板上有j个A,文本中有i个A的情况下最小的生成步数,则递推公式为:当j < i 时,dp[i][j] = min(dp[i - j][j] + 1);而dp[i][i] = min(dp[i][j] + 1), 其中j < i。这样最后返回dp[n].begin()和dp[n].end()中间的最小数即可。不过这种O(n^2)的空间复杂度没有通过测试。

2、O(n)的动态规划:

其实可以把DP的时间复杂度降低到O(n)的。我们定义dp[i]表示生成i个A所需要的最小步数,则首先把dp[i]初始化为i(这是因为当n >= 2的时候,我们可以通过先复制一个A,然后不断粘贴实现)。然后让j从i - 1不断循环到2,检查j,如果j是i的因数,那么就可以通过首先生成j个A,然后将这j个A复制后,粘贴 (i / j) - 1次实现。这样就可以顺利通过测试了。注意到这里dp[i]只依赖于另外一个dp[j],所以这种动态规划可以进一步简化成为递归实现(见下面代码片段中的version 2)。

3、递推法:

在网上看到的既不用动态规划,也不用递归的版本,我觉得这是最优秀的一个解法了:当n >= 2的时候,我们的最优策略就是尽可能地生成n的最大因数个A(例如 n / d个),然后将其复制1遍,再粘贴 d - 1次。为了让n / d尽可能的大,我们就让d尽可能的小,所以我们让d从2开始循环。当找到一个d之后,我们接下来只需要解决生成n /d个A的问题,所以在循环中让n变为n / d即可。这样算法的时间复杂度就直接降低到了O(logn),可谓已经到了极致了。

代码

1、O(n^2)的动态规划:

class Solution {
public:int minSteps(int n) {vector<vector<int>> dp(n + 1, vector<int>(n + 1, INT_MAX));dp[1][0] = 0, dp[1][1] = 1;for (int i = 1; i <= n; ++i) {for (int j = 1; j < i; ++j) {if (dp[i - j][j] < INT_MAX) {dp[i][j] = min(dp[i][j], dp[i - j][j] + 1);}if (dp[i][j] < INT_MAX) {dp[i][i] = min(dp[i][i], dp[i][j] + 1);}}}return *(min_element(dp[n].begin(), dp[n].end()));}
};

2、O(n)的动态规划:

class Solution {
public:int minSteps(int n) {// version 1: DPif (n == 1) {return 0;}vector<int> dp(n + 1, INT_MAX);for (int i = 2; i <= n; ++i) {dp[i] = i;for (int j = i - 1; j > 1; --j) {if (i % j == 0) {dp[i] = dp[j] + (i / j);break;}}}return dp[n];// version 2: recursion/*if (n == 1) {return 0;}for (int i = n - 1; i > 1; --i) {if (n % i == 0) {return minSteps(i) + n / i;}}return n;*/}
};

3、递推法:

class Solution {
public:int minSteps(int n) {int s = 0;for (int d = 2; d <= n; ++d) {  // we want to make d copies of n / d 'A'swhile (n % d == 0) {s += d;n /= d;}}return s;}
};

[Leetcode] 650. 2 Keys Keyboard 解题报告相关推荐

  1. leetcode 650. 2 Keys Keyboard | 650. 只有两个键的键盘(暴力递归->傻缓存->DP)

    题目 https://leetcode.com/problems/2-keys-keyboard/description/ 题解 再一次印证了我在 总结 DP 模型套路 中说的:从递归->DP之 ...

  2. LeetCode 167.Two Sum II 解题报告

    LeetCode 167.Two Sum II 解题报告 题目描述 Given an array of integers that is already sorted in ascending ord ...

  3. [LeetCode]844. Backspace String Compare 解题报告(C++)

    [LeetCode]844. Backspace String Compare 解题报告(C++) 题目描述 Given two strings S and T, return if they are ...

  4. 【LeetCode】91. Decode Ways 解题报告(Python)

    [LeetCode]91. Decode Ways 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fux ...

  5. Leetcode 第133场周赛解题报告

    今天参加了leetcode的周赛,算法比赛,要求速度比较快.有思路就立马启动,不会纠结是否有更好的方法或代码可读性.只要在算法复杂度数量级内,基本上是怎么实现快速就怎么来了. 比赛时先看的第二题,一看 ...

  6. 【LeetCode】934. Shortest Bridge 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS + BFS 相似题目 参考资料 日期 题目地 ...

  7. 【LeetCode】127. Word Ladder 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/word-lad ...

  8. 【LeetCode】935. Knight Dialer 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划TLE 空间换时间,利用对称性 优化空间复杂 ...

  9. 【LeetCode】275. H-Index II 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/h-index- ...

最新文章

  1. 双边滤波+ 通俗自己理解
  2. LeetCode集锦(十) - 第28题 Implement StrStr
  3. Dalvik/ART(ANDROID)中的多线程机制(4)
  4. 玩游戏提示计算机性能过低,如果玩游戏的fps低怎么办?八个问题和九个解决方案...
  5. Kotlin学习笔记 第四章 Java调用Kotlin
  6. Scala学习02——Scala类和对象
  7. Esp8266(1)
  8. 亚嵌教育李明:一生的学习
  9. ICCV 2021 Oral | 新类别发现(Novel Class Discovery)的统一目标
  10. html中空格符号以及空格字符实体的总结
  11. 2655 切木头(二分)
  12. 阿里小蜜技术学习笔记--知识点整理
  13. APScheduler如何设置任务不并发(即第一个任务执行完再执行下一个)?
  14. 语雀 添加块级模式公式
  15. 使用域控批量安装软件
  16. 7.Unity2D 横版 未受伤害时,血条缓慢变透明+伤害数值显示(浮动,大小,颜色)+协程的应用
  17. C++ getline()函数的用法
  18. html清除左侧,CSS清除浮动
  19. hashCode()方法是什么,hashCode相同代表什么
  20. YTU OJ 2914 Problem A xiaoping学构造函数

热门文章

  1. Chapter1.2:自动驾驶汽车的产生
  2. @component的作用详细介绍
  3. SQL Sever查询语句集锦
  4. 东海农场电灌站 电力运维云平台的应用与设计
  5. SpringBoot入门及YML文件详解
  6. error与exception的区别
  7. (七)play之yabe项目【CRUD】
  8. 个人贷款违约预测模型
  9. 在校大学生申请 软件著作权 需要的东西及获取手段
  10. 【三年面试五年模拟】算法工程师的独孤九剑秘籍(第九式)