• 650. 2 Keys Keyboard


    问题

    初始化有一个字符"A",可以进行两项操作:全部复制,或者粘贴。最少多少步能产生n个A。
    Input: 3
    Output: 3
    Explanation: 全部复制(“A”),然后粘贴两次,三步操作。

    思路

    C记为全部复制,P记为粘贴。考虑多次连续复制是没有意义的,所以正常操作是一次C后面跟多次P。比如操作序列为CPPCPPPCPPPP,考虑每次C会对复制信息产生变化,可以根据C分组成[CPP] [CPPP] [CPPPP]。

    [CPP] [CPPP] [CPPPP],第一个分组会产生长度为3的A,第二个分组是在第一个分组的基础上操作的,会产生3乘以4个A。容易发现以下结论,令各组的长度分别为g1, g2, g3,执行第一个分组后产生g1个A,执行第二个分组后产生g1*g2个A,执行第三个分组后产生g1*g2*g3个A。每个分组长度至少为2,因为只有复制C是产生不了A的。

    所以我们实际要做的就是把n分解成多个数的乘积(每个数,即分组长度,至少为2),使得这些数加起来最小。
    跟另一道题343. Integer Break相反,Integer Break是把n分解成多个数的和,使这些数的积最大。

    那么如何分解呢,假设现在分成了两个数的乘积,n = n1 x n2,它们的和为n1 + n2,这个时候n1如果能继续分解成p和q使得和更小,则有n = p x q x n2,使得 (p + q + n2) < n1 + n2,此时 p + q < n1 = p x q。

    也就是说只要因子可以分解成p和q,并且p + q < pq,我们就可以继续分解,使得和越来越小。什么时候p+q < pq,其实就是(p-1)(q-1)>1,二者等价。在正整数里,当p>=2且q>=3时即可。

    如果这个数本身是质数,就不可分解了,否则的话,就可以一直分解,使得所有因子为质数。所以先从2开始分解,分到不能用2分解了,就用3,分到不能用3分解了,就用5,7,11,13等等(因为测试数据在1000以内,可以把1000以内的质数写出来)。

    实际实现中,可以直接从2开始,逐一往上递增即可,即2,3,4,5,6,7,8,9。

    时间复杂度最坏是O(N),比如997要从2一直遍历到997。最快是O(logN),比如1024,分10次2即可。

    时间复杂度O(n),空间复杂度O(1)

    代码

    class Solution(object):
        def minSteps(self, n):
            """
            :type n: int
            :rtype: int
            """
            ans = 0
            prime = 2
            while n > 1:
                while n % prime == 0:
                    ans += prime
                    n /= prime
                prime += 1
            return ans
    

    类似题目

    343. Integer Break

  • 相关阅读:
    WLAN设备接入过程
    802.1帧格式、帧类型详解
    SSID、BSSID、BSS等区分
    802.11协议详解
    bit、Byte、Mbps、Mb/s区别
    WLAN认证技术
    freemarker的简单使用案例
    关于throw、throws、try--catch的问题
    String去重方法
    常用典型的sql语句
  • 原文地址:https://www.cnblogs.com/liaohuiqiang/p/9767621.html
Copyright © 2020-2023  润新知