有趣的小练习(持续更新~)
有趣的小练习
使用生成器实现range()函数
def my_range(start, stop=None, step=1):
if not stop: # 如果只传了一个参数,就调整参数
stop = start # 相当于 start=0,stop = 传的值
start = 0
while start < stop: # 只要start小于stop 就执行输出语句
yield start
start += step # start += step 实现步长
for i in my_range(0, 10, 2):
print(i)
- 以下是使用递归做的类range()函数,但是执行效果并不理想,直接进行了打印操作的执行,有点类似python2.0版本的range哈哈哈哈
def index(start, stop=None, step=1):
if not stop: # 如果只传了一个参数,就调整参数
stop = start # 相当于 start=0,stop = 传的值
start = 0
if start >= stop:
return stop
print(start)
return index(start=start + step, stop=stop, step=step)
index(10, 20)
算法-二分法
- 二分法
- 基本逻辑就是将数据一分为二,与所需要查找的内容进行大小比较
- 二分法操作的前提是需要将数据进行排序
# 通过递归函数进行二分法
list1 = [1, 2, 3, 4, 5, 9, 89, 567, 34, 4562, 56]
# 查找某个数字是否存在于列表中
list1.sort()
# 将数据列表排序
num_find = input('请输入要查找的数字:').strip()
num_find = int(num_find) # 转成数字类型
def half(data_list, target_num):
# 定义二分法的函数
try:
mid_index = len(data_list) // 2
# 通过对数据列表进行除数取整,得到中间数的索引
if target_num > data_list[mid_index]:
# 将所查找的数据与中间数对比
list_right = data_list[mid_index + 1:]
# 如果查找数比中间数大,那么中间数左边的数据就可以舍弃
# 此处切片的索引加1 是因为也可以将当前中间数舍去,切皮取左舍右
# 定义一个新列表通过切片拿到中间数右边的所有值
return half(list_right, target_num)
# 进行递归的传递,传递的新值为,切片过的数据和查找数,进行下一轮判断
elif target_num < data_list[mid_index]:
# 如果查找数比中间数小,那么中间数右边的数据就可以舍弃
# 定义一个新列表通过切片拿到中间数左边的所有值
list_left = data_list[:mid_index]
# 此处不用是因为切片,取左舍右,在:右边时中间数自动就被舍弃了
return half(list_left, target_num)
# 进行递归的传递,传递的新值为,切片过的数据和查找数,进行下一轮判断
else:
# 当既不大于中间数,也不小于中间数,只有一种等于‘=’的情况了
return "在表中找到了!"
except IndexError:
# 异常捕获,当列表读取完毕且没有读取到就输出表中不存在
return f"表中不存在!"
print(half(list1, num_find))
生成器面试题
# 求和
def add(n, i):
return n + i
# 调用之前是函数 调用之后是生成器
def test():
for i in range(4):
yield i
g = test() # 初始化生成器对象
for n in [1, 10]:
g = (add(n, i) for i in g)
res = list(g)
print(res)
#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23]
#D. res=[21,22,23,24]
# 求和
def add(n, i):
return n + i
# 调用之前是函数 调用之后是生成器
def test():
for i in range(4):
yield i
g = test() # 初始化生成器对象
for n in [1, 10]:
g = (add(n, i) for i in g)
'''
一共2次循环,n 第一次等于1,n 第二次等于 10
第一次,n = 1
g = ((add(n, i) for i in g)
只是一个生成器,并未被调用
第二次,n = 10
g = ((add(n, i) for i in ((add(n, i) for i in g))
就相当于 for 循环了生成器,所以生成器被调用了
g = ((add(10, i) for i in ((add(10, i) for i in g))
答案从20起始,因为 for 循环的第一个值等于10,而add()函数的第一个也等于10
答案中只有C符合条件
'''
res = list(g)
print(res)
#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23]
#D. res=[21,22,23,24]
动态的展示日志最后一条
实现动态查看最新一条日志的效果
import time # 导入的一个时间模块
# linux里面的一条命令:tail -f access.log
with open('access.log', mode='rb') as f:
f.seek(0, 2)
while True:
line = f.readline()
if len(line) == 0:
# 没有内容
time.sleep(0.5) # 睡眠0.5秒
else:
print(line.decode('utf-8'), end='')
计算列表单词出现的次数
words = 'my name is lea4ning , my age is 20 '
words_list = words.split(' ') # 按空格切分
words_count = {}
for i in words_list: # 遍历单词列表
if i in words_count: # 如果单词存在于字典中
words_count[i] += 1 # 字典的值自增1次
elif i not in words_count:
words_count[i] = 1 # 如果不在,字典的值就等于1次
print(words_count)
# {'my': 2, 'name': 1, 'is': 2, 'lea4ning': 1, ',': 1, 'age': 1, '20': 1, '': 1}
使用列表展示堆和栈的概念
# 堆
ll = []
ll.append(111) # 先进
ll.append(222)
ll.append(333)
print(ll)
print(ll.pop(0)) # 先出
print(ll.pop(0))
print(ll.pop(0))
'''
[111, 222, 333]
111
222
333
'''
# 栈
ll2 = []
ll2.append(111) # 先进
ll2.append(222)
ll2.append(333)
print(ll2)
print(ll2.pop())
print(ll2.pop())
print(ll2.pop()) # 后出
'''
[111, 222, 333]
333
222
111
'''
递归练习
以下是一些递归练习题,从简单到难:
- 计算阶乘: 编写一个递归函数,计算给定正整数
n
的阶乘。 - 斐波那契数列: 编写一个递归函数,计算斐波那契数列的第
n
项。斐波那契数列的定义是:F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2)
。 - 反转字符串: 编写一个递归函数,将输入的字符串反转。例如,输入字符串 "hello",输出 "olleh"。
- 二进制搜索: 实现一个递归函数,在有序整数列表中执行二进制搜索。函数应该返回目标元素的索引,如果不存在,则返回 -1。
- 二分法
- 二进制搜索(Binary Search)是一种在有序数组中查找特定元素的算法。算法的基本思想是通过将数组分成两半,然后比较目标值与中间元素的大小关系,从而确定目标值可能在数组的哪一半中。
- 汉诺塔问题: 实现汉诺塔问题的递归解法。汉诺塔是一个经典问题,要求将一堆盘子从一个柱子移动到另一个柱子,其中大盘子不能放在小盘子上。
- 子集生成: 编写一个递归函数,生成给定集合的所有子集。
- 图的深度优先搜索(DFS): 实现图的深度优先搜索算法,以找到图中的所有节点。
- 归并排序: 实现归并排序算法,其中包括递归步骤。将一个列表分为两半,分别对两半进行排序,然后合并两个有序列表。
阶乘
# [1]阶乘 f(n) = n *f(n-1)
# f(0) = 1
# f(1) = 1
def factorial(n):
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
print(factorial(5))
斐波那契
# [2]斐波那契 f(n) = f(n-1) + f(n -2)
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
return fib(n-1) + fib(n-2)
print(fib(10))
反转字符串
# [3]反转字符串
def reverse_string(input_str):
# 基本情况:空字符串或只有一个字符,直接返回
if len(input_str) <= 1:
return input_str
# 交换第一个字符和最后一个字符
first_char = input_str[0]
last_char = input_str[-1]
# 递归:反转去掉首尾字符的子串
reversed_substring = reverse_string(input_str[1:-1])
# 将首尾字符交换后的字符串拼接起来
reversed_str = last_char + reversed_substring + first_char
return reversed_str
# 示例
input_string = "hello"
result = reverse_string(input_string)
print(result)
二分法
# [4]二分法
def half_num(list, target):
try:
half_index = len(list) // 2
if target > list[half_index]:
new_list = list[half_index+1:]
return half_num(new_list, target)
elif target < list[half_index]:
new_list = list[:half_index]
return half_num(new_list, target)
else:
return half_index
except IndexError:
return -1
lis1 = [1, 2, 3, 4, 5, 6, 7]
target = int(input("请输入想要查找的数字,不存在则为-1,存在则返回索引值:").strip()) # 以理想状态下,不考虑验证
print(half_num(lis1, target))