有趣的小练习(持续更新~)

有趣的小练习

使用生成器实现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
'''

递归练习

以下是一些递归练习题,从简单到难:

  1. 计算阶乘: 编写一个递归函数,计算给定正整数 n 的阶乘。
  2. 斐波那契数列: 编写一个递归函数,计算斐波那契数列的第 n 项。斐波那契数列的定义是:F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2)
  3. 反转字符串: 编写一个递归函数,将输入的字符串反转。例如,输入字符串 "hello",输出 "olleh"。
  4. 二进制搜索: 实现一个递归函数,在有序整数列表中执行二进制搜索。函数应该返回目标元素的索引,如果不存在,则返回 -1。
    1. 二分法
    2. 二进制搜索(Binary Search)是一种在有序数组中查找特定元素的算法。算法的基本思想是通过将数组分成两半,然后比较目标值与中间元素的大小关系,从而确定目标值可能在数组的哪一半中。
  5. 汉诺塔问题: 实现汉诺塔问题的递归解法。汉诺塔是一个经典问题,要求将一堆盘子从一个柱子移动到另一个柱子,其中大盘子不能放在小盘子上。
  6. 子集生成: 编写一个递归函数,生成给定集合的所有子集。
  7. 图的深度优先搜索(DFS): 实现图的深度优先搜索算法,以找到图中的所有节点。
  8. 归并排序: 实现归并排序算法,其中包括递归步骤。将一个列表分为两半,分别对两半进行排序,然后合并两个有序列表。

阶乘

# [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))
posted @ 2024-01-18 08:58  Lea4ning  阅读(2)  评论(0编辑  收藏  举报