LeetCode 650 - 2 Keys Keyboard
LeetCode 第650题
Initially on a notepad only one character 'A' is present. You can perform two operations on this notepad for each step:
- Copy All: You can copy all the characters present on the notepad (partial copy is not allowed).
- 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,而你的键盘上只有两个按键,复制全部和粘贴, 现在要获得 n 个A,问你最少需要按多少次按键才能获得
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];
}
};
这个解法分为两步
- 查看获得 i 个A时剪贴板上A的个数 currClipBoard, 然后看以这个剪贴板进行粘贴能不能更新后面的k个A的次数。
- 以目前的 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的更多相关文章
- [LeetCode] 650. 2 Keys Keyboard 两键的键盘
Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...
- [leetcode] 650. 2 Keys Keyboard (Medium)
解法一: 暴力DFS搜索,对每一步进行复制还是粘贴的状态进行遍历. 注意剪枝的地方: 1.当前A数量大于目标数量,停止搜索 2.当前剪贴板数字大于等于A数量时,只搜索下一步为粘贴的状态. Runtim ...
- [LeetCode] 651. 4 Keys Keyboard 四键的键盘
Imagine you have a special keyboard with the following keys: Key 1: (A): Print one 'A' on screen. Ke ...
- LC 650. 2 Keys Keyboard
Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...
- 【LeetCode】650. 2 Keys Keyboard 只有两个键的键盘(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 素数分解 日期 题目地址:https://le ...
- 650. 2 Keys Keyboard
Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...
- 650. 2 Keys Keyboard复制粘贴的次数
[抄题]: Initially on a notepad only one character 'A' is present. You can perform two operations on th ...
- [LeetCode] 2 Keys Keyboard 两键的键盘
Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...
- [LeetCode] 4 Keys Keyboard 四键的键盘
Imagine you have a special keyboard with the following keys: Key 1: (A): Print one 'A' on screen. Ke ...
随机推荐
- python利用urllib实现的爬取京东网站商品图片的爬虫
本例程使用urlib实现的,基于python2.7版本,采用beautifulsoup进行网页分析,没有第三方库的应该安装上之后才能运行,我用的IDE是pycharm,闲话少说,直接上代码! # -* ...
- C# 导出数据到Excel模板中(转)
今天做报表的时候遇到了多表头的问题,而且相应的报表的格式都一样.所以就采用了报表模板的方式来进行. 第一步:在开发的当前项目中引入:Microsoft.Office.Interop.Excel:Sys ...
- JavaScript学习日志(二):面向对象的程序设计
1,ECMAScript不像其他面向对象的语言那样有类的概念,它的对象与其他不同. 2,ECMAScript有两种属性:数据属性和访问器属性.([[]]这种双中括号表示属性为内部属性,外部不可直接访问 ...
- Wireshark抓包TCP三次握手数据
抓包工具 - Wireshark(详细介绍与TCP三次握手数据分析) 功能使用的详细介绍 wireshark(官方下载网站: http://www.wireshark.org/),是用来获取网络数据封 ...
- hashMap和treeMap
前言 首先介绍一下什么是Map.在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.这就是我们平时说的键值对. ...
- 201521123091 《Java程序设计》第9周学习总结
Java 第九周总结 第九周的作业. 目录 1.本章学习总结 2.Java Q&A 3.码云上代码提交记录及PTA实验总结 1.本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异 ...
- 201521123059 《Java程序设计》第七周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 参考资料: XMind 2. 书面作业 Q1: ArrayList代码分析 1.1 解释ArrayList的contains ...
- 201521123060 《Java程序设计》第3周学习总结
1. 本周学习总结 2. 书面作业 1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; p ...
- 201521123019 《Java程序设计》第3周学习总结
1. 本周学习总结 2. 书面作业 (1)代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; ...
- 201521123012 《Java程序设计》第二周学习总结
1. 本章学习总结 1.Java中String和StringBuilder的区别. 2.Arrays()的用法. 2.课后作业 1.使用Eclipse关联jdk源代码(截图),并查看String对象的 ...