法1:动态规划
想法:
- copy all 算 1 次操作;paste 算 1 次操作
- 数组 dp:dp[i] 表示打印出 i 个 ‘A’ 的最少操作次数。
- 从前向后更新 dp :找 i % j == 0 中,j 的最大值(n >= i > j >= 1)
- dp[i] = dp[j] + 1 + (i / j - 1)
dp[j]表示得到 j 个 A 所需的最少操作次数;1 表示 copy 这 j 个 A,(i / j - 1) 表示 paste 的次数(本身已经存在一份 j 个 A,故减去 1 次) - 整理上式:dp[i] = dp[j] + i / j
- 返回dp[n]
/**
* @param {number} n
* @return {number}
*/
var minSteps = function(n) {
// copy all算 1 次操作;paste算 1 次操作
// 数组dp
// 从前向后更新:找 i % j == 0 中,j 的最大值(n >= i > j >= 1)
// 返回dp[n]
var dp = [], i = 0, j = 0
for(i = 0; i <= n; i++) {
dp[i] = 0;
}
for(i = 2; i <= n; i++) {
// 可以如此:j = Math.floor(i / 2),效率会更高
for(j = i - 1; j >= 1; j--) {
if(i % j == 0) {
// 1: copy; (i / j - 1): paste
// dp[i] = dp[j] + 1 + (i / j - 1);
dp[i] = dp[j] + i / j;
break;
}
}
}
return dp[n];
};
法2:递归
看了题解
想法:
- 对于n:
- 如果 n 是素数,则只能由 1 个 A 经过多次 paste 得到,答案为 1 + n - 1 = n(copy 1 次,paste n - 1次)
- 如果 n 不是素数,则找到 n 的最大约数 i ,并求得到 i 个 A 的最少操作数 minSteps(i);答案为:minSteps(i) + 1 + n / i - 1 = minSteps(i) + n / i
/**
* @param {number} n
* @return {number}
*/
var minSteps = function(n) {
if(n == 1) {
return 0;
}
var i = 0;
for(i = Math.floor(n / 2); i >= 2; i--) {
if(n % i == 0) { // i 是 n 的约数,n 不是素数
return minSteps(i) + n / i;
}
}
return n;
};
本文介绍了如何使用动态规划和递归方法解决LeetCode第650题,即在只有两个键的键盘上打印出指定数量的'A'字符的最小操作次数。动态规划策略通过维护一个数组dp来更新最少操作次数,而递归策略则根据数字是否为质数来确定操作次数。两种方法都详细阐述了思路和公式推导。
369

被折叠的 条评论
为什么被折叠?



