LeetCode 第650题

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'.

题目的意思就是在一个文本编辑器里,有个一字符A,而你的键盘上只有两个按键,复制全部粘贴, 现在要获得 nA,问你最少需要按多少次按键才能获得

n的范围为[1, 1000];


这道题在Leetcode上的分类为动态规划,那么我就尝试使用动态规划,自底向上递推的做。

class Solution {
public:
int minSteps(int n) {
vector<int> dp(n + 1, 0x7FFFFFFF);
vector<int> clipBoard(n + 1, 0);
dp[1] = 0;
dp[2] = 2;
clipBoard[2] = 1;
for (int i = 2; i <= n; ++i) { int currClipBoard = clipBoard[i];
int j = i;
for (int j = i, step = 1; j + currClipBoard <= n; ++step, j+=currClipBoard) {
if (dp[j + currClipBoard] > dp[i] + step) {
dp[j + currClipBoard] = dp[i] + step;
clipBoard[j + currClipBoard] = currClipBoard;
}
} if (i * 2 <= n && dp[i * 2] > dp[i] + 2) {
dp[i * 2] = dp[i] + 2;
clipBoard[i * 2] = i;
}
} return dp[n];
}
};

这个解法分为两步

  1. 查看获得 i 个A时剪贴板上A的个数 currClipBoard, 然后看以这个剪贴板进行粘贴能不能更新后面的k个A的次数。
  2. 以目前的 i 个A为起点,复制 i 个A到剪贴板,看能否更新后续的 i * 2 个 A的次数

    dp[n] 就是结果。

最终结果是通过了。


然后在Discussion区中发现了一个更加高明的做法,代码也很简洁。

class Solution {
public:
int minSteps(int n) {
if (n == 1) return 0;
for (int i = 2; i < n; i++)
if (n % i == 0) return i + minSteps(n / i);
return n;
}
};

我尝试解释这段代码的含义:

不难证明,如果n为质数,我们只能够通过n次操作来获得n个A,例如

n = 2 : 复制, 粘贴

n = 3 : 复制, 粘贴,粘贴。

n = 5 : 复制, 粘贴 *4

因为 n 为质数时,它的因数只有 1 和 本身,所以 n 为质数时,只能够通过复制 第一个 A, 然后通过 n -1 次粘贴来获得。

所以我们可以看出,想要把 x 个A扩展成 kx 个的话,如果 k 为 素数的话,最少需要 k 个按键操作才能实现。

那如果 n 不为 素数呢?

我们可以 把 n 划分成两个数的乘积 n = a * b;

那么 f(n) = f(a) + b;

那么b要怎么取呢?

我们假设b取的是合数(即可以拆成两个或多个的乘积)。我们假设b能够拆成2个素数的乘积 (b = m*n)

由于所有的素数都大于1。对于下面的公式是恒成立的:

m * n >= m + n;

所以 对于 b的选择来说,我们应该选择素数。

即对于b为合数的情况

f(a) + b > f(a) + m + n = f(a*m) + n

b的选择就已经很明显了。

于是问题转化为对n进行分解,分解成k个素数的乘积,然后求这k个素数的和。

这也是Discussion中算法的原理。

LeetCode 650 - 2 Keys Keyboard的更多相关文章

  1. [LeetCode] 650. 2 Keys Keyboard 两键的键盘

    Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...

  2. [leetcode] 650. 2 Keys Keyboard (Medium)

    解法一: 暴力DFS搜索,对每一步进行复制还是粘贴的状态进行遍历. 注意剪枝的地方: 1.当前A数量大于目标数量,停止搜索 2.当前剪贴板数字大于等于A数量时,只搜索下一步为粘贴的状态. Runtim ...

  3. [LeetCode] 651. 4 Keys Keyboard 四键的键盘

    Imagine you have a special keyboard with the following keys: Key 1: (A): Print one 'A' on screen. Ke ...

  4. LC 650. 2 Keys Keyboard

    Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...

  5. 【LeetCode】650. 2 Keys Keyboard 只有两个键的键盘(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 素数分解 日期 题目地址:https://le ...

  6. 650. 2 Keys Keyboard

    Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...

  7. 650. 2 Keys Keyboard复制粘贴的次数

    [抄题]: Initially on a notepad only one character 'A' is present. You can perform two operations on th ...

  8. [LeetCode] 2 Keys Keyboard 两键的键盘

    Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...

  9. [LeetCode] 4 Keys Keyboard 四键的键盘

    Imagine you have a special keyboard with the following keys: Key 1: (A): Print one 'A' on screen. Ke ...

随机推荐

  1. 分布式memcached-虚拟节点

    1.通过memcached服务器下的不同端口来达到模拟多台服务器的效果 2.假设现在有三台memcached服务器,本地分别使用11211,11212,11213三个端口来模拟 ①打开端口 ②连接端口 ...

  2. window的设置属性

    1.windowAnimationStyle 用于设置一组window动画的引用style资源,window的动画属性由R.styleable.WindowAnimation定义. Winow动画类属 ...

  3. cocos quick lua 输入框点击穿透的问题处理方案。

    条件:当前版本quick-3.3 -lua,系统 win7. 问题:在输入框(textField或者editbox,下文"输入框"就代表这两种)打开的情况下弹出其他界面盖住输入框, ...

  4. ionic3 自动创建启动背景splash以及图标icon

    在新建的项目文件夹下的 resources下就是我们放置图标以及启动背景图片的位置了. 如果现在我们想生成自己的图片的启动背景以及图片,我们需要把resources下的 icon.png 以及spla ...

  5. 201521123083《Java程序设计》第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 上周这张图没理解完,继续 2. 书面作业 本次PTA作业题集多线程 1互斥访问与同步访问完成题集4-4(互斥访问) ...

  6. 201521123020 《Java程序设计》第3周学习总结

    本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 书面作业 1.代码 ...

  7. 201521123005 《java程序设计》 第二周学习总结

    1. 本周学习总结 ·java中的字符串及String的用法 "=="比较的是两字符串的地址,而不是内容 String类的对象是不可变的,创建之后不能进行修改 ·数组Array的用 ...

  8. 201521123080《Java程序设计》第2周学习总结

    1.本周学习总结 a.学习了如何建立远程仓库和本地仓库并建立连接. b.学习了一些基础语法. 2.书面作业 Q1.使用Eclipse关联jdk源代码,并查看String对象的源代码(截图)?分析Str ...

  9. 201521123040《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...

  10. Log4J:Log4J三大组件:Logger+Appender+Layout 格式化编程详解

    快速了解Log4J Log4J的三个组件: Logger:日志记录器,负责收集处理日志记录     (如何处理日志) Appender:日志输出目的地,负责日志的输出  (输出到什么 地方) Layo ...