题目的链接在这里:https://leetcode-cn.com/problems/2-keys-keyboard/
题目大意
最初在一个记事本上只有一个字符 'A'。你每次可以对这个记事本进行两种操作:Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。
Paste (粘贴) : 你可以粘贴你上一次复制的字符。
给定一个数字 n 。你需要使用最少的操作次数,在记事本中打印出恰好 n 个 ‘A’。输出能够打印出 n 个 ‘A’ 的最少操作次数。
一、示意图
二、解题思路
动态规划
代码如下:
class Solution {
public int minSteps(int n) {
//首先第一步肯定是copy all 然后之后的操作,就是有一个pass 他初始值是1
//dp[i] 怎么来的呢 他只可能是通过 Paste 来的 而且是上一次的 copy 得到的数值
//应该是这样的 dp[i]表示到达i用的最小的操作数 而他可以是 dp[k]进行一次 paste 相当于是dp[k]+1
//dp[i-paste]+1 这个就是他的最后结局吧
//我放弃了 看了没什么写这道题 直接就去看了解析
//这里需要用到 乘除法来计算位置 因为粘贴操作是倍数增加的 dp[i]表示延长到i的最小操作次数
//如果j可以被i整除 也就是i是j的倍数 所以就相当于是 dp[i]=dp[j]+dp[i/j] 后面这个是什么意思呀
//dp[i/j] 很妙的在于 因为从j->i 的操作次数 就等于 从1-> i/j 的操作次数 所以dp[i/j]就相当于是 dp[j]->dp[i]的操作次数
int dp[]=new int[n+1];
//然后就是所有的赋初值 dp[0]肯定是0 dp[1]呢 为什么也是0.. 原来是题目的缘故 他本来就是有一个A的。
//所以dp[1]就直接等于 0 而dp[2]=先copy all 赋值到A 然后把A再粘贴一个A上去 而对于其他的 最差的就是n 相当于就是copy 一下
//然后之后都是粘贴
for(int i=2;i<=n;i++){
dp[i]=i;
//然后开始比较
for(int j=2;j<=Math.sqrt(n);j++){
if(i%j==0){
dp[i]=dp[j]+dp[i/j];
//有没有break2问题不大
break;
//这里还有个细节是break 如果不break的话 他会被覆盖 i=6的时候 j可以等于 2 等于 3 也等于 6
//原来是因为 dp[6]=dp[2]+dp[3] 等于dp[6]=dp[3]+dp[2] 但是如果是16这种呢 可以是 2 8 也可以是 4 4 的
//
}
}
}
return dp[n];
}
}