#求200以内的素数和_阶乘leetcode刷题(十五):数学1(素数,最大公约数,进制转换,阶乘)...

这篇博客探讨了素数分解、最大公约数计算、进制转换以及阶乘的算法实现。文章介绍了如何通过素数分解表示任意整数,以及快速计算最大公约数和最小公倍数的方法。此外,还讲解了如何使用厄拉多塞筛法高效找出一定范围内的质数数量。进制转换部分包括从十进制到七进制的转换,以及二进制字符串的加法运算。最后,讨论了求解阶乘后零的个数问题,提出了一种O(logn)时间复杂度的解决方案。
摘要由CSDN通过智能技术生成

e544d7b4326fb906c35766e8cd217602.png

今天来讲讲剩下几块内容:素数,最大公约数,进制转换,阶乘.

素数

素数分解

每一个数都可以分解成素数的乘积,例如 84 = 2^2 * 3^1 * 5^0 * 7^1 * 11^0 * 13^0 * 17^0 * …

整除

令 x = 2^m0 * 3^m1 * 5^m2 * 7^m3 * 11^m4 * … 令 y = 2^n0 * 3^n1 * 5^n2 * 7^n3 * 11^n4 * …

如果 x 整除 y(y mod x == 0),则对于所有 i,mi <= ni。

x 和 y 的 最大公约数 为:gcd(x,y) = 2^min(m0,n0) * 3^min(m1,n1) * 5^min(m2,n2) * ...

x 和 y 的 最小公倍数 为:lcm(x,y) = 2^max(m0,n0) * 3^max(m1,n1) * 5^max(m2,n2) * ...

最大公约数

对于最大公约数问题,因为需要计算 a % b ,而这个操作是比较耗时的,可以利用减法和移位操作来替换它。

对于 a 和 b 的最大公约数 f(a, b),有:


1. 如果 a 和 b 均为偶数,f(a, b) = 2*f(a/2, b/2);

2. 如果 a 是偶数 b 是奇数,f(a, b) = f(a/2, b);

3. 如果 b 是偶数 a 是奇数,f(a, b) = f(a, b/2);

4. 如果 a 和 b 均为奇数,f(a, b) = f(a, a-b);

乘 2 和除 2 都可以转换为移位操作。

204. 计数质数

统计所有小于非负整数 n 的质数的数量。

示例:

输入: 10

输出: 4

解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

这题搜到一个非常牛逼的算法,叫做厄拉多塞筛法. 比如说求20以内质数的个数,首先0,1不是质数.2是第一个质数,然后把20以内所有2的倍数划去.2后面紧跟的数即为下一个质数3,然后把3所有的倍数划去.3后面紧跟的数即为下一个质数5,再把5所有的倍数划去.以此类推.

代码的实现上用了非常好的技巧:

def countPrimes(self, n: int) -> int:
        if n < 3:
            return 0     
        else:
            # 首先生成了一个全部为1的列表
            output = [1] * n
            # 因为0和1不是质数,所以列表的前两个位置赋值为0
            output[0],output[1] = 0,0
             # 此时从index = 2开始遍历,output[2]==1,即表明第一个质数为2,然后将2的倍数对应的索引
             # 全部赋值为0. 此时output[3] == 1,即表明下一个质数为3,同样划去3的倍数.以此类推.
            for i in range(2,int(n**0.5)+1): 
                if output[i] == 1:
                    output[i*i:n:i] = [0] * len(output[i*i:n:i])
         # 最后output中的数字1表明该位置上的索引数为质数,然后求和即可.
        return sum(output)

在上面遍历索引的时候用到了一个非常好的技巧. 即i是从(2,int(n**0.5)+1)而非(2,n).这个技巧是可以验证的,比如说求9以内的质数个数,那么只要划掉sqrt(9)以内的质数倍数,剩下的即全为质数. 所以在划去倍数的时候也是从i*i开始划掉,而不是i+i.


这个解法真是太赞了!又学到了很多~~~ 和大家分享一下

504. 七进制数

给定一个整数,将其转化为7进制,并以字符串形式输出。


示例 1:

输入: 100

输出: "202"

示例 2:

输入: -7

输出: "-10"

注意: 输入范围是 [-1e7, 1e7] 。

class Solution(object):
    def convertToBase7(self, num):
        """
        :type num: int
        :rtype: str
        """
        A = []
        if num == 0:
            return "0"
        if num < 0:
            s = '-'
        else:
            s = ''
        num = abs(num)
        while(num > 0):
            A.append(num % 7)
            num = num // 7 
        A = A[::-1]
        for i in A:
            s = s + str(i)
        return s

172. 阶乘后的零

给定一个整数 n,返回 n! 结果尾数中零的数量。


示例 1:

输入: 3

输出: 0

解释: 3! = 6, 尾数中没有零。

示例 2:

输入: 5

输出: 1

解释: 5! = 120, 尾数中有 1 个零.

说明: 你算法的时间复杂度应为 O(log n) 。

class Solution(object):
    def trailingZeroes(self, n):
        """
        :type n: int
        :rtype: int
        """
 
        if n < 5:
            return 0
        else:
            m = 1
            sum = 0
            while n>= (5**m):
                sum += n // (5**m)
                m += 1
        return sum

67. 二进制求和

给定两个二进制字符串,返回他们的和(用二进制表示)。


输入为非空字符串且只包含数字 1 和 0。


示例 1:

输入: a = "11", b = "1"

输出: "100"

示例 2:

输入: a = "1010", b = "1011"

输出: "10101"

方法一:

class Solution(object):
    def addBinary(self, a, b):
        return bin(int(a,2) + int(b,2))[2:]

方法二:

class Solution:
    def addBinary(self, a: str, b: str) -> str:
        # 短字符串前端补零,保证两者长度相等

        if len(a) > len(b):
            b = '0'* (len(a)-len(b)) + b
        elif len(a) < len(b):
            a = '0'* (len(b) - len(a)) + a

        res, carry = '', '0'
        for a_, b_ in reversed(list(zip(a, b))):
 
            if a_ == '0' and b_ == '0':                                 # 当前位两个数都是0
                r = carry
                carry = '0'
            elif a_ == '1' and b_ == '0' or a_ == '0' and b_ == '1':    # 当前位两个数不同
                r = '1' if carry == '0' else '0'
                carry = '1' if carry == '1' else '0'
            else:                                                       # 当前位两个数都是1
                r = '1' if carry == '1' else '0'
                carry = '1'

            res = r + res

        if carry == '1':                                                # 如果还有进位
            res = '1' + res
        return res

415. 字符串相加

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。

注意:


num1 和num2 的长度都小于 5100.

num1 和num2 都只包含数字 0-9.

num1 和num2 都不包含任何前导零。

你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式。

class Solution(object):
    def addStrings(self, num1, num2):
        """
        :type num1: str
        :type num2: str
        :rtype: str
        """
        l = max(len(num1),len(num2))
        num1 = num1.zfill(l)
        num2 = num2.zfill(l)
 
        p = 0
        r = ''
        for i in range(l):
            n1 = num1[l-i-1]
            n2 = num2[l-i-1]
            rr = int(n1) + int(n2) + p
            p = rr // 10
            r = str(rr%10) + r
        if p:
            r = '1' + r 
        return r

希望本文能对你有所帮助!

最后打个小广告,我的公众号,会写点学习心得,喜欢可以关注下!~!

4f0ecd214618965d0fd82e8525f83ed8.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值