leetcode
leetcode 551 ~ 600
两个键的键盘

两个键的键盘

难度:

标签:

题目描述

代码结果

运行时间: 31 ms, 内存: 16.0 MB


/*
 * Problem Statement: Starting with a single character 'A', you can perform two operations: 'Copy All' (copies all the characters in the notepad) and 'Paste' (pastes the last copied characters). Given a number 'n', determine the minimum number of operations required to produce exactly 'n' characters.
 * 
 * Solution Approach: Similar to the Java approach, we use a stream to iterate over the possible factors and sum them up when the number 'n' can be divided by these factors. This approach also calculates the minimum steps by finding the prime factors of 'n'.
 */
import java.util.stream.IntStream;
 
public class Solution {
    public int minSteps(int n) {
        if (n == 1) return 0;
        return IntStream.rangeClosed(2, n)
            .filter(i -> n % i == 0)
            .flatMap(i -> {
                int[] arr = new int[n];
                int count = 0;
                while (n % i == 0) {
                    arr[count++] = i;
                    n /= i;
                }
                return IntStream.of(arr).limit(count);
            })
            .sum();
    }
}

解释

方法:

这个题解采用的是素数分解的思路。对于任意一个大于1的整数n,可以将其分解为一系列素数的乘积。例如,12=2*2*3。题目要求的是打印出n个'A'所需的最少操作次数,实际上就等于n的素数分解式中所有素数的和。因为对于一个素数因子p,我们需要执行p次'Paste'操作和一次'Copy All'操作,总共p+1次操作。而n的素数分解的结果就是这些素数因子的集合,操作次数就是这些素数的和。题解中使用了从小到大枚举素数因子的方法,依次将n除以素数,同时累加操作次数,最后如果剩余的n大于1,则说明是一个大于sqrt(n)的素数因子,需要再加上n。

时间复杂度:

O(sqrt(n) * log n)

空间复杂度:

O(1)

代码细节讲解

🦆
题解中提到的`素数分解的思路`是如何与`Copy All`和`Paste`操作相对应的?能否详细解释一下这种映射关系?
在题解中,每个素数因子p的操作代表了用最优策略创建p个'A'的步骤。首先,我们需要有一个'A',然后执行一次`Copy All`将其复制,接下来进行p-1次`Paste`操作,将这个'A'粘贴p-1次,从而累计获得p个'A'。因此,对于每个素数因子p,总共需要1次`Copy All`和p-1次`Paste`,共p次操作。但考虑到最初的'A'需要首次创建,所以每个素数因子的总操作次数实际上是p。因此,通过素数分解,我们将n分解成多个素数因子的乘积,每个素数因子p的操作步骤相当于是创建了p个'A'。最终,所有这些操作步骤的累加即为解决问题所需的最小操作次数。
🦆
为什么在素数分解方法中,对于每一个素数因子p,操作次数是p+1次而不是仅仅p次?
实际上,每个素数因子p的操作次数应该是p次,而不是p+1次。这包括1次`Copy All`和p-1次`Paste`。初始的一个'A'不需要通过`Copy All`和`Paste`获得,因此对于每个因子p,总共需要p次操作来达到复制p个'A'的目的。这可能是对题解的解释中的一个小误会。
🦆
在计算过程中,当n大于2时直接将n加到结果中,这是基于什么样的假设?是否意味着n此时一定是素数?
当在计算过程中,n仍大于2时直接将n加入结果,这是基于假设n是一个素数的前提。题解通过素数分解,从最小的素数开始除尽n中所有可整除的素数因子,最终如果n大于2,则剩余的n不能被任何小于或等于它的素数整除,因此n本身必须是一个素数。这样的处理是确保所有因素都考虑到,没有遗漏任何操作步骤。
🦆
题解只适用到了简单的变量进行计算,是否存在任何风险或缺陷,例如在特定情况下的效率问题或者潜在的错误?
题解采用的素数分解算法在执行上是有效的,但在特定情况下,尤其是当n非常大时,其效率可能会成问题。素数分解的过程需要迭代到sqrt(n),这对于非常大的n可能会导致执行时间较长。此外,如果未优化求素数的过程,反复检测每个数是否为素数也会增加计算负担。尽管如此,对于大多数实际问题规模,这种方法应该是可行的。然而,对于极端情况或者需要高效处理大量数据的情况,可能需要更高效的算法或者实现优化。

相关问题

四个键的键盘

四个键的键盘

坏了的计算器

在显示着数字 startValue 的坏计算器上,我们可以执行以下两种操作:

  • 双倍(Double):将显示屏上的数字乘 2;
  • 递减(Decrement):将显示屏上的数字减 1

给定两个整数 startValue 和 target 。返回显示数字 target 所需的最小操作数。

 

示例 1:

输入:startValue = 2, target = 3
输出:2
解释:先进行双倍运算,然后再进行递减运算 {2 -> 4 -> 3}.

示例 2:

输入:startValue = 5, target = 8
输出:2
解释:先递减,再双倍 {5 -> 4 -> 8}.

示例 3:

输入:startValue = 3, target = 10
输出:3
解释:先双倍,然后递减,再双倍 {3 -> 6 -> 5 -> 10}.

 

提示:

  • 1 <= startValue, target <= 109