以往公司的面试题

本文详细介绍了斐波那契数列的多种实现方式,包括直接法、动态规划和递归,并分析了它们的时间复杂度。同时,通过爬楼梯问题展示了斐波那契数列的应用。此外,还探讨了数字序列中特定位置对应数字的查找算法,通过动态规划和数学推理找到了高效解决方案。
摘要由CSDN通过智能技术生成

题目一

大家都知道斐波那契数列,现在要求输入一个整数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 个台阶。你有多少种不同的方法可以爬到楼顶呢?

也是三种方法

  1. 动态规划
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]
  1. 递归 时间复杂度过大

题目二:

数字以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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jianafeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值