[LeetCode] 650. 2 Keys Keyboard

原题链接: https://leetcode.com/problems/2-keys-keyboard/

1. 题目描述

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:
The n will be in the range [1, 1000].

开始时,屏幕上有1个A,有两种操作:

  1. 复制屏幕上的全部A
  2. 粘贴
    现在要通过这两种操作,获得n个A,请问需要多少步操作?不论复制还是粘贴,都会算1步。

2. 解题思路

我们把复制操作简写为c,粘贴操作简写为p,例如,获得AA的方法就是cp,获得AAA的方法就是cpp

我们把前14个的操作过程都写出来,就可以很轻松的看到其中的规律了。
在这里插入图片描述

  1. 若n==1,步数为0
  2. 若n为素数,步数为n本身
  3. 若n为合数,步数就是n的因子加起来的和。比如6 = 3*2,那么3+2=5就是6个A需要的步数。

或者可以这么想,既然总步数越少越好,那么肯定是尽量复制 “A的个数更多的” 子序列。所以需要先找到n的最大因子。
比如n=12,可以整除12的数有6、4、3、2,其中最大的因子是6,6个A复制粘贴一次就可以达到12了,因此要想办法怎么变出6个A来,于是结果就是

6个A所需要的步数 + 2 = 12个A的步数
然后递归去求6个A所需要的步数就行了。

再比如,n=21,可以整除21的数有3、7,其中7最大,于是就要想办法先达到7个A的状态,有了7个A,就复制一次,粘贴2次就可以达到21个A,
于是求解方法就是
7个A所需要的步数 + 3 = 21个A的步数

递归实现

class Solution {
    public int minSteps(int n) {
		if(n ==1) {
			return 0;
		}
		int ans = n;
		for(int i=n-1; i>1 ;i--) {
			if(n%i == 0) {
				ans = n/i + minSteps(i);
				break;
 			}
		}
		return ans;	
	}
}

递归实现需要5ms。
在这里插入图片描述

同样的思路,如果用动态规划也可以实现,用一个数组存储之前求的步数。但是由于需要计算出所有n之前的数,因此速度要比递归慢很多。

动态规划实现

public class Solution {
	
	public int minSteps(int n) {
		
		if(n ==1) {
			return 0;
		}
		
		int[] dp = new int [n+1];
		for(int i = 2 ; i<=n ; i++) {
			dp[i] = i;//一开始无论素数还是合数,都默认为i本身
			for(int j = i-1 ; j>1 ;j--) {
				if( i%j == 0) {
					dp[i] = dp[j] + i/j;
					break;
				}
			}
		}
		return dp[n];			
	}
}

动态规划实现需要30ms。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值