作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/2-keys-keyboard/description/

题目描述

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

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’,问最少经过多少次操作(每次复制/粘贴分别算一次操作),写字板上’A’的个数才能为 n。

注意不能手动敲一个’A’上去,必须复制粘贴!

解题方法

递归

我们先分析递归的方法,递归的思想是由上向下

举个例子:当 n = 36 的时候。

36 = 18 * 2 = 3 * 3 * 2 * 2

如果我们想获得 36 个相同的A,可以先获得 18 个'A',然后复制 1 次,粘贴 1 次,于是就有了 36 个'A'。这就是 36 = 18 * 2 的含义。然后再思考怎么得到 18 个'A',这就是递归。

当起始只有一个'A'的情况下,一种得到36个'A'的方案为:

  1. 复制 1 次,粘贴 2 次,得到 'AAA'
  2. 在上面的基础上,复制 1 次,粘贴 2 次,得到 'AAAAAAAAA'
  3. 在上面的基础上,复制 1 次,粘贴 1 次,得到 18 个 'A'
  4. 在上面的基础上,复制 1 次,粘贴 1 次,得到 36 个 'A'

因为复制和粘贴都算一次操作,所以上面得到了 3 * 3 * 2 * 2 = 36 个'A'

我们可以得出结论:

  1. 如果 n 是素数的话,我们只能通过复制 1 次A,然后粘贴 n - 1 次的方式才能得到 n 个A。总的操作了 n 次。
  2. 如果 n = i * j 的话,最快得到 n 的方式是先得到 i ,复制 1 次,然后再粘贴 j - 1 次,总的就有了 n 个A。总的操作了 minSteps(i) + 1 + j - 1 = minSteps(i) + j = minSteps(i) + n / i 次。

于是就有了递归的解法。该解法是,先让 i 从 2 开始遍历找到 n - 1,判断 i 是不是 n 的因子,如果 i 是 n 的因子,那么总的需要操作 minSteps(i) + n / i次。如果从 2 到 n - 1 没有 n 的因子,那么 n 是个素数,必须操作 n 次。

Python代码如下。

class Solution:
def minSteps(self, n: int) -> int:
if n == 1:
return 0
for i in range(2, n):
if n % i == 0:
return self.minSteps(n // i) + i
return n

素数分解

上面已经给了递归的做法,看了 36 个 'A' 的分解之后,我们发现题目要求的就是 36 的所有素因子之和。素因子是指,该因子不可再次拆分。

为什么非得拆解成 素因子 呢?因为当一个因子还可以分解成更小的因子的时候,那么分解后的结果会更小。

比如 36 = 18 * 2,题目所求的最优结果是 18 + 2 = 20 么?显然不是,因为如果把18 拆开 36 = 3 * 6 * 2,此时复制粘贴的个数只需要 3 + 6 + 2 = 12 次。但这仍然不是最优结果,36 = 3 * 2 * 3 * 2,此时复制粘贴的个数只需要 3 + 2 + 3 + 2 = 10 次。此时已经是最优了。

具体证明就是要证明 m * n > m + n,等价于求 (m - 1)*(n - 1) > 1,当 m 和 n 大于 2 的时候上式永远成立。

至于代码,就是让我们求 n 能拆成哪些素因子。我们让 d 试探是否为因子从 2 开始递增,如果 n 能被 d 整除时,此时的 d 是 n 的一个素因子,求复制粘贴次数的结果中增加 d ;而且如果 d 是个素因子,那么要一次性把 n 中除掉所有的 d。

Python 代码如下。

class Solution:
def minSteps(self, n: int) -> int:
res = 0
d = 2
while n > 1:
while n % d == 0:
res += d
n //= d
d += 1
return res

参考:

https://leetcode-cn.com/problems/2-keys-keyboard/solution/zhi-you-liang-ge-jian-de-jian-pan-by-leetcode/

日期

2018 年 3 月 15 日 —— 雾霾消散,春光明媚
2020 年 5 月 30 日 —— 答辩顺利,心情大好

【LeetCode】650. 2 Keys Keyboard 只有两个键的键盘(Python)的更多相关文章

  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 650 - 2 Keys Keyboard

    LeetCode 第650题 Initially on a notepad only one character 'A' is present. You can perform two operati ...

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

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

  5. Java实现 LeetCode 650 只有两个键的键盘(递归 || 数学)

    650. 只有两个键的键盘 最初在一个记事本上只有一个字符 'A'.你每次可以对这个记事本进行两种操作: Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的). ...

  6. Leetcode 650.只有两个键的键盘

    只有两个键的键盘 最初在一个记事本上只有一个字符 'A'.你每次可以对这个记事本进行两种操作: Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的). Past ...

  7. 【LeetCode】650. 只有两个键的键盘

    只有两个键的键盘 最初在一个记事本上只有一个字符 'A'.你每次可以对这个记事本进行两种操作: 1.Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的). 2. ...

  8. LC 650. 2 Keys Keyboard

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

  9. [Swift]LeetCode650. 只有两个键的键盘 | 2 Keys Keyboard

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

随机推荐

  1. mysql—MySQL数据库中10位时间戳转换为标准时间后,如何对标准时间进行加减X天处理

    在这篇的缘由:问题:"FROM_UNIXTIME(timeline,'%Y-%m')"的结果(2020-06)做月份增加1月或者减少1月的计算处理,想着直接在结果上+1但是,结果为 ...

  2. Redis学习小结

    在7月中旬,我成功入职实习,通过进入公司,认识到了个人与企业巨大的差距,首先就是对于中间件的使用,ElasticSearch.Redis.Kafka等等,都是听过却从未使用过的,然而在任务下达之后,激 ...

  3. CSS区分Chrome和Firefox

    CSS区分Chrome和FireFox 描述:由于Chrome和Firefox浏览器内核不同,对CSS解析有差别,因此常会有在两个浏览器中显示效果不同的问题出现,解决办法如下: /*Chrome*/ ...

  4. android studio 使用 aidl(三)权限验证

    这篇文章是基于android studio 使用 aidl (一) 和 android studio 使用 aidl(二) 异步回调 下面的代码都是简化的,如果看不懂请先移步上2篇文章 网上的东西太坑 ...

  5. 【分布式】ZooKeeper权限控制之ACL(Access Control List)访问控制列表

    zk做为分布式架构中的重要中间件,通常会在上面以节点的方式存储一些关键信息,默认情况下,所有应用都可以读写任何节点,在复杂的应用中,这不太安全,ZK通过ACL机制来解决访问权限问题,详见官网文档:ht ...

  6. Hibernate持久化标志符生成策略

    generator子元素定义持久化标识符的生成策略,为持久化类对应的数据库表的主键找到了赋值方法,HIbernate默认将使用assigned的持久化标识符生成策略.关系型数据库的主键定义方式:(1) ...

  7. hive 启动不成功,报错:hive 启动报 Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/mapred/MRVersi

    1. 现象:在任意位置输入 hive,准备启动 hive 时,报错: Exception in thread "main" java.lang.NoClassDefFoundErr ...

  8. 【Service】【Database】【Cache】Redis

    1. 简介: 1.1. redis == REmote DIctionary Server 1.2. KV cache and store, in-memory, 持久化,主从(sentinel实现一 ...

  9. Docker从入门到精通(三)——概念与执行流程

    前面我们大概介绍了docker是什么以及如何安装docker,但是对里面出现的一些名词,可能大家还不熟悉,这篇文章就来为大家解惑. 1.容器化平台 Docker 是提供应用打包,部署与运行应用的容器化 ...

  10. Redis cluster 集群命令合集

    目录 一.常用命令 二.操作命令 三.redis-trib.rb脚本 一.常用命令 打印集群的信息 CLUSTER INFO 列出集群当前已知的所有节点(node),以及这些节点的相关信息. CLUS ...