题型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])