骚操作系列(ctrl+c 和 ctrl+v 的算法问题)
- 2020 年 2 月 25 日
- 筆記
来源:小浩算法
作者:程序员浩哥

今天为大家分享一道关于“复制”+“粘贴”的题目。
话不多说,直接看题。

01
第650题:只有两个键的键盘

第650题:最初在一个记事本上只有一个字符 'A'。你每次可以对这个记事本进行两种操作:Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。Paste (粘贴) : 你可以粘贴你上一次复制的字符。
给定一个数字 n 。你需要使用最少的操作次数,在记事本中打印出恰好 n 个 'A'。输出能够打印出 n 个 'A' 的最少操作次数。
示例 1:
输入: 3
输出: 3
解释:
最初, 我们只有一个字符 'A'。
第 1 步, 我们使用 Copy All 操作。
第 2 步, 我们使用 Paste 操作来获得 'AA'。
第 3 步, 我们使用 Paste 操作来获得 'AAA'。
说明:
n 的取值范围是 [1, 1000]

(请叫我秀儿~)
02
题目分析

本题的思路,在于想明白复制和粘贴过程中的规律,找到如何组成N个A的最小操作数。
我们从最简单的开始分析,假如我们给定数字为1,那啥也不用做,因为面板上本来就有一个A。(废话…)

假如我们给定数字为2,那我们需要做C-P,共计2次操作来得到。

假如我们给定数字为3,那我们需要做C-P-P,共计3次操作来得到。

假如我们给定数字为4,我们发现好像变得不一样了。因为我们有两种方法都可以得到目标。(C-P-C-P)

或者(C-P-P-P)

但是需要的步骤还是一样。

好了,到这里为止,STOP!通过上面的分析,我们至少可以观察出:如果 i 为质数,那么 i 是多少,就需要粘贴多少次。即:素数次数为本身的结论。如 两个A = 2,三个A = 3,五个A = 5。
那对于合数又该如何分析呢?(自然数中除能被1和本身整除外,还能被其他的数整除的数)这里我们直接给出答案:合数的次数为将其分解质因数的操作次数的和。解释一下,这是个啥意思?举个例子:
比如30,可以分解为:3*2*5。什么意思呢?我们演示一遍:首先复制1,进行2次粘贴得到3。然后复制3,进行1次粘贴得到6。然后复制6,进行4次粘贴得到30。总共需要(CPPCPCPPPP)

注意:这里由于每一次都需要进行一次复制,所以直接就等于分解质因数的操作次数的和。并且分解的顺序,不会影响到结果。
综合上面的分析,我们得出分析结果:
1、质数次数为其本身。
2、合数次数为将其分解到所有不能再分解的质数的操作次数的和。
03
Go语言示例

分析完毕,代码自成:
func minSteps(n int) int { res := 0 //找寻从2到n所有可以被n整除的质数 for i := 2; i <= n; i++ { //找到第一个可以整除的数字 for n%i == 0 { res += i n /= i } } return res }
我顺便加了个Java语言的代码版本
int minSteps(int n) { int res = 0; for(int i = 2; i <= n; i++){ while(n % i == 0){ res += i; n = n / i; } } return res; }
骚出边界有木有:

我整理了几百本CS相关的电子书,全部都放在了这个Github:https://github.com/iamshuaidi/CS-Book(点击阅读原文直达,电脑打开更佳)