Leetcode Algorithms - Dynamic Programming:650. 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:

  1. Copy All: You can copy all the characters present on the notepad (partial copy is not allowed).
  2. 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:
The n will be in the range [1, 1000].

分析

最开始的想法是设d(i)是得到i个A的最小步数。那么如果存在下面两种情况,可以利用状态转移方程通过d(j)求出d(i)的值:

  1. 存在i % j = 0,那么d(i) = d(j) + 1 + (i / j - 1)。中间的加一是复制当前的所有字符,i / j - 1是需要粘贴的次数。
  2. 当前内容有j个A的时候,通过继续粘贴若干次,可以得到i个A。那么状态转移方程就是d(i) = d(j) + (i - j) / paste[j],其中paste[j]表示得到j个A时复制板里的内容。

上面的思路看起来没有错,但其实这两种情况是一样的。考虑第二种情况,j肯定是paste[j]的倍数,因为根据题意,j肯定是至少进行了一次复制后再若干次粘贴得到的,所以j肯定是最近一次复制的字符个数num的倍数。那么显然i肯定是num的倍数,所以第二种情况和第一种情况本质上是一样的。

于是,只需要对每个小于i的值j都做一次第一种情况的判断,就可以计算出d(i)。

在写算法时,有2个小技巧:

  1. 可以按从大到小的顺序对j值进行判断。因为题目要求最小步数,使用值较大的因子的步数肯定大于等于使用值较小因子的步数。
  2. 可以只对j <= i / 2的j值进行判断。因为对于大于i/2的j值,i永远不可能成为j的倍数。

代码

class Solution {
public:
    int minSteps(int n) {
        int *d = new int[n + 1];
        d[1] = 0;
        for (int i = 2; i <= n; i++) {
            for (int j = i/2; j > 0; j--) {
                if (i % j == 0) {
                    d[i] = d[j] + i/j;
                    break;
                }
            }
        }
        return d[n]; 
    }
};

引用

题目提供的答案值得参考,引用一下:

class Solution {
    public int minSteps(int n) {
        int ans = 0, d = 2;
        while (n > 1) {
            while (n % d == 0) {
                ans += d;
                n /= d;
            }
            d++;
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值