[LeetCode] 2 Keys Keyboard 两键的键盘

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

这道题只给了我们两个按键,如果只能选择两个按键,那么博主一定会要复制和粘贴,此二键在手,天下我有!!!果然,这道题就是给了我们复制和粘贴这两个按键,然后给了我们了一个A,我们的目标时利用这两个键来打印出n个A,注意复制的时候时全部复制,不能选择部分来复制,然后复制和粘贴都算操作步骤,问我们打印出n个A需要多少步操作。对于这种有明显的递推特征的题,我们要有隐约的感觉,一定要尝试递归和DP。递归解法一般接近于暴力搜索,但是有时候是可以优化的,从而能够通过OJ。而一旦递归不行的话,那么一般来说DP这个大杀器都能解的。还有一点,对于这种题,找规律最重要,DP要找出递推公式,而如果无法发现内在的联系,那么递推公式就比较难写出来了。所以,我们需要从简单的例子开始分析,试图找规律:

当n = 1时,已经有一个A了,我们不需要其他操作,返回0

当n = 2时,我们需要复制一次,粘贴一次,返回2

当n = 3时,我们需要复制一次,粘贴两次,返回3

当n = 4时,这就有两种做法,一种是我们需要复制一次,粘贴三次,共4步,另一种是先复制一次,粘贴一次,得到AA,然后再复制一次,粘贴一次,得到AAAA,两种方法都是返回4

当n = 5时,我们需要复制一次,粘贴四次,返回5

当n = 6时,我们需要复制一次,粘贴两次,得到AAA,再复制一次,粘贴一次,得到AAAAAA,共5步,返回5

通过分析上面这6个简单的例子,我想我们已经可以总结出一些规律了,首先对于任意一个n(除了1以外),我们最差的情况就是用n步,不会再多于n步,但是有可能是会小于n步的,比如n=6时,就只用了5步,仔细分析一下,发现时先拼成了AAA,再复制粘贴成了AAAAAA。那么什么情况下可以利用这种方法来减少步骤呢,分析发现,小模块的长度必须要能整除n,这样才能拆分。对于n=6,我们其实还可先拼出AA,然后再复制一次,粘贴两次,得到的还是5。分析到这里,我想解题的思路应该比较清晰了,我们要找出n的所有因子,然后这个因子可以当作模块的个数,我们再算出模块的长度n/i,调用递归,加上模块的个数i来更新结果res即可,参见代码如下:

解法一:

class Solution {

public:
    int minSteps(int n) {
        if (n == 1) return 0;
        int res = n;
        for (int i = n - 1; i > 1; --i) {
            if (n % i == 0) {
                res = min(res, minSteps(n / i) + i);
            }
        }
        return res;
    }
};

下面这种方法是用DP来做的,我们可以看出来,其实就是上面递归解法的迭代形式,思路没有任何区别,参见代码如下:

解法二:

class Solution {

public:
    int minSteps(int n) {
        vector<int> dp(n + 1, 0);
        for (int i = 2; i <= n; ++i) {
            dp[i] = i;
            for (int j = i - 1; j > 1; --j) {
                if (i % j == 0) {
                    dp[i] = min(dp[i], dp[j] + i / j);
                }
            }
        }
        return dp[n];
    }
};

下面我们来看一种省空间的方法,我们不需要记录每一个中间值,而是通过改变n的值来实时累加结果res,参见代码如下:

解法三:

class Solution {

public:
    int minSteps(int n) {
        int res = 0;
        for (int i = 2; i <= n; ++i) {
            while (n % i == 0) {
                res += i;
                n /= i;
            }
        }
        return res;
    }
}; 

参考资料:

https://discuss.leetcode.com/topic/97590/java-dp-solution

https://discuss.leetcode.com/topic/97623/loop-best-case-log-n-no-dp-no-extra-space-no-recursion-with-explanation

本文转自博客园Grandyang的博客,原文链接:[LeetCode] 2 Keys Keyboard 两键的键盘

,如需转载请自行联系原博主。

时间: 2024-10-15 14:47:47

[LeetCode] 2 Keys Keyboard 两键的键盘的相关文章

[LeetCode] 4 Keys Keyboard 四键的键盘

Imagine you have a special keyboard with the following keys: Key 1: (A): Print one 'A' on screen. Key 2: (Ctrl-A): Select the whole screen. Key 3: (Ctrl-C): Copy selection to buffer. Key 4: (Ctrl-V): Print buffer on screen appending it after what has

怎么在win7下开启键盘鼠标键用键盘来控制鼠标移动呢?

  第一.打开鼠标键 (1)按Ctrl+Esc组合键打开开始选单,按S键然后按C键打开控制面板; (2)按方向键移动到"辅助选项",按回车键打开它的属性对话框; (3)按Ctrl+Tab组合键切换到"鼠标"页,按Alt+M组合键选中"使用鼠标键"选项; (4)按Alt+S组合键进入鼠标键设置对话框,按Alt+T选中"最高速度"项,然后按右方向键将其调至最大,同理,将"加速"项调至最大; (5)按两次回车键退

win7开启键盘鼠标键用键盘来控制鼠标的移动

  启用鼠标键就是用用键盘来控制鼠标的移动,在Windows7系统中这个选项在控制面板的轻松访问中心--使键盘更易于使用中,下面是图文说明: 打开控制面板--轻松访问 选择更改键盘的工作方式 选择使用键盘控制鼠标 1.打开鼠标键 (1)按Ctrl+Esc组合键打开开始选单,按S键然后按C键打开控制面板; (2)按方向键移动到"辅助选项",按回车键打开它的属性对话框; (3)按Ctrl+Tab组合键切换到"鼠标"页,按Alt+M组合键选中"使用鼠标键&quo

winform-C# Winform项目中,如何实现响应键盘的Tab键以及键盘的回车键

问题描述 C# Winform项目中,如何实现响应键盘的Tab键以及键盘的回车键 C# Winform项目中,有个form窗体,在form窗体中有一个Panel控件, 在Panel控件中包函六个Label控件(label1.label2.label3.label4.label5.label6),这六个Label控件从上到下排成一列. 如何实现以下两个功能: 1.如何实现通过点击键盘的Tab键可以实现从上到下的依次移动选择六个Lable控件. 2.在选中对应的Label控件后,如何实现点击键盘的回

&amp;amp;#9733;会用这两键,你就是电脑高手了

学习微软操作系统的圣经!! 更多实用技能请关注@实用技能  学会用这二个键,你就是电脑高手了,一个是windows键,另一个是Ctrl键. 一.windows键 1.很多时候,需要暂时离开座位去做别的事情,如果对自己的电脑安全很重视,不妨按住windows键后,再按L键,这样电脑就直接锁屏了,这样就不用担心电脑的资料外泄啦 2.要找电脑上的文件时,一般人会先找到"我的电脑",然后点击打开,而高手总是很酷的,轻轻按下键盘上的Windows键不放然后再按E键,直接打开电脑的资源管理器,而一

★会用这两键,你就是电脑高手了

学习微软操作系统的圣经!! 更多实用技能请关注@实用技能  学会用这二个键,你就是电脑高手了,一个是windows键,另一个是Ctrl键. 一.windows键 1.很多时候,需要暂时离开座位去做别的事情,如果对自己的电脑安全很重视,不妨按住windows键后,再按L键,这样电脑就直接锁屏了,这样就不用担心电脑的资料外泄啦 2.要找电脑上的文件时,一般人会先找到"我的电脑",然后点击打开,而高手总是很酷的,轻轻按下键盘上的Windows键不放然后再按E键,直接打开电脑的资源管理器,而一

&amp;#9733;会用这两键,你就是电脑高手了

学习微软操作系统的圣经!! 更多实用技能请关注@实用技能  学会用这二个键,你就是电脑高手了,一个是windows键,另一个是Ctrl键. 一.windows键 1.很多时候,需要暂时离开座位去做别的事情,如果对自己的电脑安全很重视,不妨按住windows键后,再按L键,这样电脑就直接锁屏了,这样就不用担心电脑的资料外泄啦 2.要找电脑上的文件时,一般人会先找到"我的电脑",然后点击打开,而高手总是很酷的,轻轻按下键盘上的Windows键不放然后再按E键,直接打开电脑的资源管理器,而一

iOS 上常用的两个功能:点击屏幕和return退出隐藏键盘和解决虚拟键盘挡住UITextField的方法

转自:http://blog.csdn.net/xiaotanyu13/article/details/7711954 iOS上面对键盘的处理很不人性化,所以这些功能都需要自己来实现, 首先是点击return和屏幕隐藏键盘 这个首先引用双子座的博客 http://my.oschina.net/plumsoft/blog/42545,他的文章写的很好,对大家的理解很有好处. 在 iOS 程序中当想要在文本框中输入数据,轻触文本框会打开键盘.对于 iPad 程序,其键盘有一个按钮可以用来关闭键盘,但

开启win7键盘鼠标键的步骤

  启用鼠标键就是用用键盘来控制鼠标的移动,在Windows7系统中这个选项在控制面板的轻松访问中心--使键盘更易于使用中,下面是图文说明: 打开控制面板--轻松访问 选择更改键盘的工作方式 选择使用键盘控制鼠标 1.打开鼠标键 (1)按Ctrl+Esc组合键打开开始选单,按S键然后按C键打开控制面板; (2)按方向键移动到"辅助选项",按回车键打开它的属性对话框; (3)按Ctrl+Tab组合键切换到"鼠标"页,按Alt+M组合键选中"使用鼠标键&quo