珍宝鸭的力扣练习(11):基本数学问题

本文提供了一系列算法题目,包括质数统计、丑数统计、整数次幂计算等,通过具体实例介绍了不同算法题目的解决思路和方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题型1:特殊数字

题目1:质数统计

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

方法一:枚举
很直观的思路是我们枚举每个数判断其是不是质数。考虑到如果 y是 x 的因数,那么 x/y也必然是 x的因数,因此我们只要校验 y 或者 x/y
即可。而如果我们每次选择校验两者中的较小数,则不难发现较小数一定落在 [2,\sqrt{x}]的区间中,因此我们只需要枚举 [2,sqrt{x}]中的所有数即可,这样单次检查的时间复杂度从 O(n)降低至了 O(sqrt{n})

方法二:埃氏筛
如果 x是质数,那么大于 x 的 x 的倍数 2x,3x,… 一定不是质数,设 isPrime[i] 表示数 i 是不是质数,如果是质数则为 1,否则为 0。从小到大遍历每个数,如果这个数为质数,则将其所有的倍数都标记为合数(除了该质数本身),即 0,这样在运行结束的时候我们即能知道质数的个数。这种方法的正确性是比较显然的:这种方法显然不会将质数标记成合数;另一方面,当从小到大遍历到数 x 时,倘若它是合数,则它一定是某个小于 x 的质数 y 的整数倍,故根据此方法的步骤,我们在遍历到 y 时,就一定会在此时将 x 标记为 0。因此,这种方法也不会将合数标记为质数。

class Solution(object):
    def countPrimes(self, n):
        is_prime=[1 for i in range(n)]
        ans=0
        for i in range(2,n):
            if is_prime[i]:
                ans+=1
                for j in range(i,n,i):
                    is_prime[j]=0
        return ans

题目2:丑数统计

我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
丑数的递推性质: 丑数只包含因子 2, 3, 5 。
因此有 “丑数 = 某较小丑数× 某因子” (例如:10 = 5* 2)
在这里插入图片描述

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        dp, a, b, c = [1] * n, 0, 0, 0
        for i in range(1, n):
            n2, n3, n5 = dp[a] * 2, dp[b] * 3, dp[c] * 5
            dp[i] = min(n2, n3, n5)
            if dp[i] == n2: a += 1
            if dp[i] == n3: b += 1
            if dp[i] == n5: c += 1
        return dp[-1]

题型2:设计公式

题目1:设计整数次方

实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。

输入: 2.00000, 10
输出: 1024.00000

输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
题解:递归
当exponent是0的时候,直接返回1即可,
当exponent小于0的时候,需要把它转化为正数才能更方便计算,同时base要变为1/base。
当exponent大于0的时候要分为两种情况,一种是偶数,一种是奇数。

class Solution(object):
    def __init__(self):
        self.result = 1
    def myPow(self, x, n):
        """
        :type x: float
        :type n: int
        :rtype: float
        """
        if n==0: return 1
        if n<0: return self.myPow(1/x,-n)

        if n%2==0:
           return self.myPow(x*x,n//2)
        else:
            return x*self.myPow(x*x,n//2)

题解:迭代

class Solution(object):
    def __init__(self):
        self.result = 1
    def myPow(self, x, n):
        b=n
        if n<0:
            n=-n
        if n==0: return 1
        result=1
        while n!=0:
            if n%2==1:
                result*=x
            x *= x
            n=n//2
        return result if b>0 else 1/result

题目2:设计1+2+…+n

求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

题解:根据python短路效应:
n > 1 && sumNums(n - 1) // 当 n = 1 时 n > 1 不成立 ,此时 “短路” ,终止后续递归

class Solution:
    def __init__(self):
        self.res = 0
    def sumNums(self, n: int) -> int:
        n > 1 and self.sumNums(n - 1)
        self.res += n
        return self.res

题型3:统计类

题目1:统计1的个数

根据当前位 cur 值的不同,分为以下三种情况:
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

当 cur = 0 时: 此位 1 的出现次数只由高位 决定
计算公式为:high×digit

当 cur = 1 时: 此位 1 的出现次数由高位与低位共同决定
计算公式为:high×digit+low+1

当 cur > 1 时: 此位 1 的出现次数只由高位 决定
计算公式为:(high+1)×digit

class Solution(object):
    def countDigitOne(self, n):
        left,right=n,0
        i=1
        result=0
        while right!=n:
            cur=left%10
            left = left // 10
            if cur==0:
                result+=left*i
            elif cur==1:
                result+=(left)*i+right+1
            else:
                result+=(left+1)*i

            right=i*cur+right

            i*=10
        return result

题目2:数字序列

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。

在这里插入图片描述

class Solution(object):
    def findNthDigit(self, n):
        digit,start,end=1,1,9
        while n>digit*(end-start+1):
                n-=digit*(end-start+1)
                digit+=1
                end=end*10+9
                start*=10
        a,b=(n-1)//digit,(n-1)%digit
        return int(str(start+a)[b])
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值