四个键的键盘
难度:
标签:
题目描述
代码结果
运行时间: 21 ms, 内存: 16.0 MB
/*
* 四个键的键盘问题:
* 有四个特殊的键:A、Ctrl-A、Ctrl-C和Ctrl-V。Ctrl-A 选择整个屏幕的文本,Ctrl-C 将选择的文本复制到缓冲区,Ctrl-V 将缓冲区的文本粘贴到屏幕上。
* 给定一个整数 N,表示按键的次数,编写一个函数在屏幕上显示最多 'A' 字符的个数。
* 思路:
* 1. 对于每个按键次数,我们可以有三种选择:按A,Ctrl-A+C+V(选择复制粘贴)。
* 2. 我们需要找出每个按键次数下最多的A字符数。
* 3. 使用动态规划的方法来解决这个问题。
*/
import java.util.stream.IntStream;
public class FourKeysKeyboardStream {
public int maxA(int N) {
// dp[i] 表示按 i 次键时最多能得到多少个 'A'
int[] dp = new int[N + 1];
IntStream.rangeClosed(1, N).forEach(i -> {
// 按 A 键
dp[i] = dp[i - 1] + 1;
// 按 Ctrl-A, Ctrl-C, Ctrl-V
IntStream.range(2, i).forEach(j -> {
dp[i] = Math.max(dp[i], dp[j - 2] * (i - j + 1));
});
});
return dp[N];
}
}
解释
方法:
这道题采用动态规划的思路求解。我们定义 `dp[n]` 表示 n 次操作能得到的最多 A 的数量。对于每个状态,我们有四种选择:输入 A、复制全部、粘贴、不操作。通过枚举这四种选择,取其中能得到最多 A 的选择作为当前状态的最优解。其中,如果选择复制全部,我们需要枚举复制的起点,即 dp[j-1],其中 j 表示上一次复制全部的位置,然后将剪贴板中的内容粘贴 i-(j+1)+1 次,即可得到 dp[j-1] * (i-(j+1)+1) 个 A。最后返回 dp[n] 即可。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
在动态规划的解决方案中,为什么你选择从 `dp[i-1] + 1` 开始更新 `dp[i]`?这是否意味着每次操作默认先考虑输入一个A?
▷🦆
你的方案中提到,可以选择不操作,但实际代码实现中似乎没有体现出这一操作。请问在哪种情况下,选择不操作是有益的?
▷🦆
在计算 `dp[j - 1] * (i - (j + 1) + 1)` 时,这个公式是如何推导出来的?能否详细解释下其背后的逻辑和意义?
▷相关问题
两个键的键盘
最初记事本上只有一个字符 'A'
。你每次可以对这个记事本进行两种操作:
Copy All
(复制全部):复制这个记事本中的所有字符(不允许仅复制部分字符)。Paste
(粘贴):粘贴 上一次 复制的字符。
给你一个数字 n
,你需要使用最少的操作次数,在记事本上输出 恰好 n
个 'A'
。返回能够打印出 n
个 'A'
的最少操作次数。
示例 1:
输入:3 输出:3 解释: 最初, 只有一个字符 'A'。 第 1 步, 使用 Copy All 操作。 第 2 步, 使用 Paste 操作来获得 'AA'。 第 3 步, 使用 Paste 操作来获得 'AAA'。
示例 2:
输入:n = 1 输出:0
提示:
1 <= n <= 1000