题目一
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。n≤39
斐波那契数列很简单的公式,就是f(n) = f(n-1) + f(n-2)
如果用代码写出来,就是我会用很简单的,轮流赋值来写
首先写出完整斐波那契数列出来,直接法,不用递进法
def Fibonacci(n):
a,b,c = 0,1,0
ans = [0,1]
while True:
if c>n:return ans
else:
a,b = b, a+b
c+= 1
ans.append(b)
f = Fibonacci(5)
f
输出为:
[0, 1, 1, 2, 3, 5, 8, 13]
也可以用yield来保存 然后下一次从保存的结果开始。
那么题目是只输出n项的数字,修改一下即可。
def Fibonacci( n):
m = 2
a, b = 0,1
if n == 0 or n == 1:
return n
else:
while n!= m:
a,b = b , a+b
m += 1
return a+b
还有一种方法是 递进,即用公式 f(n) = f(n-1) + f(n-2)
class Solution:
def Fibonacci(self, n):
a,b = 0 , 1
if n == 0 or n == 1: return n
else:
return self.Fibonacci(n-1) + self.Fibonacci(n-2)
可以是可以,但是,运行时间太久。无法通过。
方法三是使用dp动态规划
def Fibonacci(n):
if n == 0 or n == 1: return n
dp = []
dp.append(0)
dp.append(1)
for i in range(2,n+1):
tmp = (dp[i-1] + dp[i-2])%1000000007
dp.append(tmp)
return dp[-1]
我都不想说话,对自己极度无语,今天面试的算法题,爬楼梯问题,我居然打不出来,明明就是很简单很简单的斐波那契数列的变形。好吧。自己资历太差了。
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
也是三种方法
- 动态规划
class Solution:
def climbStairs(self, n: int) -> int:
dp = []
dp.append(0)
dp.append(1)
dp.append(2)
for i in range(3,n+1):
tmp = dp[i-1] + dp[i-2]
dp.append(tmp)
return dp[n]
- 递归 时间复杂度过大
题目二:
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
例子
输入:n = 11
输出:0
输入:n = 3
输出:3
思想:
首先理解是那个词
数位: 10111213… 每一位都称为数位 ,记为 n;
数字: 10,11,12,13,,, 每一个成为数字,记为 num;
位数:比如数字10是一个两位数 ,所以位数为2. 记为digit;
每个位数开始的数字记为 start
对于1-9,位数digit = 1 ; 数字num总数为 9; 数位总数为9;
对于 10-99,位数digit = 2 ,数字num总数为 90; 数位n总数为 180
对于100-999,位数digit = 3,数字num 总数为900,数位n总数为 2700
所以得到的规律是
(1) digit = digit + 1 ;
(2)开始位置bgn = bgn ✖️ 10
(3)数位数量总数n = 9 ✖️ bgn ✖️ digit
我们现在假设 count_ 1 = 9(表示一位数的数位总数为 9)
count_2 = 180 (表示二位数的数位总数为 180)
count_3 = 2700(表示三位数的数位总数为 2700)
现在当n =11
由于 n=11 > count_1 = 9
于是进行
n = n - count_ 1 = 2
count_ 2 = 180
由于 n=2 < count_2= 180 所以break 现在知道 在count_2范围内。
代码如下:
digit, bgn , count = 1,1,9
while n > count:
n -= count
bgn *= 10 # 1 , 10, 100, 1000 ,,,
count = 9 * bgn * digit #9, 180, 2700,,,,
接着,我们需要找到对应的数字num 。
这就需要使用
num = start + (n - 1) // digit
这是因为下图所示:
这里的例子是n=2,所以num = 10 + (n-1)//2 = 10
所以所在数字是 10
求出所在的数字num=10之后,需要找出是哪个数位
那么用求余数公式
如下图所示:
这个时候把num=10 变成 string字符 再用余数取出来相对应的数
即
s= str(num)
ans = int(s[(n-1)%digit])
整合写出完整的函数:
def findNthDigit(n):
digit,bgn, count = 1,1,9
#找出对应的几位数范围
while n > count:
n -= count
bgn = bgn * 10
digit += 1
count = 9 * digit *bgn
#找出对应的数字 ,整除得到
num = bgn + (n-1)//digit
#找出这个数字对应的数,用求余得到
s = str(num)
ans = int(s[(n-1)%digit])
return ans
时间复杂度 是O(logn)