• YZYのPython 作业~


    2.3

    问题描述

    (n) 个人围成一圈,顺序排号。从第一个人开始报数(从 (1)(3) 报数),凡报到 (3) 的人退出圈子,问最后留下的是原来第几号的那位。

    思路分析

    实际上这是个约瑟夫环问题。但是题目没有要求复杂度,我们简单的实现就好了。

    根据关键词退出圈子,不难想到:

    • del
    • x.remove()

    于是我们很容易写出这样一个错误的代码

    n = int(input('输入数字:')) # 输入数字
    arr = list(range(1, n + 1, 1)) # 建立一个列表,存放的是号码数
    cnt = 0 # 记录当前报的号是多少
    while len(arr) > 1:
        for i in range(len(arr)):
            cnt += 1
            if (cnt % 3 == 0):
                del arr[i]
    print(arr[0])
    

    但是这个代码会报错,出现:

    IndexError: list assignment index out of range
    也就是,索引越界。
    

    为什么会出现这个问题呢?答案是:当你del or remove 一个元素之后,列表的长度会发生变化!!!

    举个例子:

    arr = [1, 2, 3]
    # 这时候我们访问 arr[2]
    print(arr[2]) 
    # 会输出 3
    del arr[1]
    # 在删除 arr[1] 之后我们再进行访问 arr[3] 会怎么样呢?
    print(arr[3])
    # IndexError: list index out of range 会出现越界的错误
    # 这是因为,del 之后,list 的长度发生了变化
    

    因此,为了避免这个问题,我们可以设置两个列表 arrbrr 。在每次操作开始前,我们保证 brr = arr

    我们寻找 brr 中的每个元素,假如发现他所报号正好 %3 == 0 ,我们就在arr里面删除它。为啥不在 brr 里面删除而在 arr 里面删呢? 因为在 arr 里面删除不会改变 brr 的长度,这样就不会出现,索引越界的情况

    代码

    """
    Problem:
    有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),
    凡报到3的人退出圈子,问最后留下的是原来第几号的那位。
    Solution:
    实际上这个是个约瑟夫环问题,但是我们简单的implementation就好了
    """
    n = int(input('输入数字:')) # 输入数字
    arr = list(range(1, n + 1, 1)) # 建立一个列表,存放的是号码数
    cnt = 0 # 记录当前报的号是多少
    
    # 循环直到列表只剩一个元素
    while len(arr) > 1:
        brr = arr[:] # 列表切片,复制列表,为下一步删除做准备
        # brr 中的每个元素进行报数,符合条件的在 arr 中删除
        for i in range(len(brr)):
            cnt += 1 # 进行报号
            if cnt % 3 == 0: # 如果报3,则去除a中的这一位
                arr.remove(brr[i])
    print(arr[0])
    

    2.4

    问题描述

    输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。

    思路分析

    这题非常简单,我们提取关键词:1.最大值2.最小值3.交换

    关于 1.2,我们需要做的是:

    1. 找到最大最小值 mxmn
    2. 找到极值对应的索引 mx_idxmn_idx

    关于 3交换,我们运用 Python 里面的元组只是:

    1. a, b = b, a 就可以实现交换

    因此整个流程:

    • 通过 max min 函数找到最大最小值
    • 通过 for 循环找到最大最小值对应的索引
    • 交换即可

    那么聪明的 yzy 能不能不看代码实现呢!

    代码

    """
    Problem:
    输入数组,最大的与第一个元素交换,最小的与最后一个元素交换,输出数组。
    Solution: 
    implementation 简单实现即可
    """
    # 简单的接收列表
    n = int(input("Please input a number as the length of list"))
    arr = [None] * n
    for i in range(n):
        x = int(input("输入元素")); arr[i] = x
    print(arr)
    # 首先找到最大的元素,最大用 mx 而不是 max 表示
    # 注意,这里找到最大的元素不管用,需要找到最大元素的索引(因为要实现交换),最小值同理
    mx, mn = max(arr), min(arr)
    mx_idx, mn_idx = -1, -1 # 初始化 最大值的下标和最小值的下标
    # 通过以下 for 循环,我们可以找到对应极值的索引
    for i in range(n):
        if arr[i] == mx and mx_idx == -1: mx_idx = i
        if arr[i] == mn and mn_idx == -1: mn_idx = i
    # 实现交换即可, 在 python 中 a, b = b, a 即可实现交换
    arr[mx_idx], arr[0] = arr[0], arr[mx_idx]
    arr[mn_idx], arr[n - 1] = arr[n - 1], arr[mn_idx]
    print(arr)
    
    # 结果
    Please input a number as the length of list7
    输入元素5
    输入元素3
    输入元素10
    输入元素3
    输入元素1
    输入元素9
    输入元素5
    [5, 3, 10, 3, 1, 9, 5]
    [10, 3, 5, 3, 5, 9, 1]
    

    3.1

    问题描述

    求一个 (3 imes3) 矩阵对角线元素之和。

    思路分析

    过于简单,可能难点在于 二维数组 如何建立吧,然后简单计算即可!!

    代码

    """
    Problem: 
    求一个3*3矩阵对角线元素之和。
    Solution: 
    implementation 然后 tot = arr[1][1] + arr[2][2] + arr[3][3]
    """
    arr = [ [None] * 3 ] * 3
    for i in range(3):
        for j in range(3):
            x = int(input("请输入(%d, %d)的元素" % (i, j))); arr[i][j] = x
    print(arr)
    # 假设计算的是 (0, 0) (1, 1) (2, 2) 的对角线之和
    tot = 0
    for i in range(3):
        tot += arr[i][i]
    print(tot)
    

    3.2

    问题描述

    一个 (5) 位数,判断它是不是回文数。即 (12321) 是回文数,个位与万位相同,十位与千位相同。

    思路分析

    这里提供一个思路,就是把数字转换为字符串,再判断是否为回文串

    例如: (num = 12321) ,我们首先转化,ss = str(num)

    然后我们可以这样表示: (ss=1 2 3 2 1),我们设两个索引:

    • left = 0 ,指向最开始,用于从左边扫描
    • right = len(ss) - 1 ,指向最后,用于从右边扫描

    为了更加清晰的作图,我们做一下变化l = left, r = right(这里你可能会看不懂,没关系,看下面!!)

    [egin{array}{l} ss=overset{l=0}{overbrace{1}};2;3;2overset{r=4}{overbrace{1}} \ ss=1;overset{l=1}{overbrace{2}};3;overset{r=3}{overbrace{2}};1 \ ss=1;2;overset{l=r=2}{overbrace{3}};2;1 end{array} ]

    我们 l 从左往右扫描,r 从右往左扫描:

    • 如果 ss[l] == ss[r] 则他们相互靠近一格。
    • 如果不同则直接 break
    • 如果 l >= r 时,说明该字符串(数字)为一个回文串。

    代码

    """
    Problem: 
    一个5位数,判断它是不是回文数。即12321是回文数,
    个位与万位相同,十位与千位相同。
    Solution: 
    可以转为 str 之后用两个下标循环处理!
    """
    import random
    # 随机生成一个 5 位数
    num = random.randint(10000, 99999)
    print("生成的五位数是: %d" % num)
    # 我们把它转为一个字符串,这样我们就能用下标访问了!
    ss = str(num)
    # 设置两个元素,从左到右,从右到左进行扫描
    left, right = 0, len(ss) - 1
    # 设置 flag ,假如 flag 为 True 则为回文,否则则不为回文
    flag = True
    while (left < right):
        # 发现有个元素不同,则肯定不回文,设置 flag = False 然后退出循环
        if (ss[left] != ss[right]):
            flag = False
            break
        left += 1 # 左边的往右
        right -= 1 # 右边的往左
    if (flag):
        print("是回文串")
    else:
        print("不是回文串")
    

    3.3

    问题描述

    (1+2!+3!+...+20!) 的和。

    思路分析

    首先阶乘的定义是啥?

    阶乘: (x! = 1 imes 2 imes cdots imes x)

    假设 (fac(x) := x!) ,我们容易得到一个推导式: (fac(x) = fac(x-1) * x)

    要计算 (1+2!+3!+...+20!) 的和,我们利用这个递推式不断计算,并在计算的过程中更新答案!

    代码

    """
    Problem: 
    求1+2!+3!+...+20!的和。
    Solution: 
    x! 代表阶乘, x! = x * (x - 1)!
    因此,我们设一个数组 fac[n],其中 fac[i] := i!, fac[i + 1] = (i + 1) * fac[i]
    """
    # 因为要计算的范围是 1 -- 20 所以设最大为 21
    fac = [None] * 21
    # 设置初值
    fac[0] = 1
    # tot --> total 代表总答案
    tot = 0
    for i in range(1, 21, 1):
        fac[i] = i * fac[i - 1]
        tot += fac[i]
    print(tot)
    # 2561327494111820313
    

    3.4

    问题描述

    有一分数序列:(dfrac{2}{1},dfrac{3}{2},dfrac{5}{3},dfrac{8}{5},dfrac{13}{8},dfrac{21}{13} cdots)求出这个数列的前 (20) 项之和。

    思路分析

    这里的难点在于发现序列分子,分母对应的规律。

    思考一下发现,上下分子分母都是一个类似斐波那契数列的规律:

    • 2, 3, 5(2+3),8(3+5)
    • 1, 2, 3(1+2),5(2+3)

    因此,我们可以先推导出分子分母各为什么,再计算答案:

    不妨设:

    • upper(i) := 第 i 个元素的分母
    • lower(i) := 第 i 个元素的分子

    显然,他们都拥有相同的规律:

    • upper(i) = upper(i - 1) + upper(i - 2)
    • lower(i) = lower(i - 1) + lower(i - 2)

    因此,我们可以先计算出上下分母分子再用一个 for 循环计算答案!

    代码

    """
    Problem:
    有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。
    Solution:
    这题有点难度,因为上面下面实际上都是一个斐波那契数列,
    不妨设上面的第 i 个为 upper(i)
    不妨设下面的第 i 个为 lower(i)
    则: upper(i) = upper(i - 1) + upper(i - 2)
    同: lower(i) = lower(i - 1) + lower(i - 2)
    通过递推式计算即可!
    """
    upper = [None] * 20
    lower = [None] * 20
    upper[0], upper[1] = 2, 3
    lower[0], lower[1] = 1, 2
    for i in range(2, 20, 1):
        upper[i] = upper[i - 1] + upper[i - 2]
        lower[i] = lower[i - 1] + lower[i - 2]
    ans = 0.0
    for i in range(20):
        ans += (upper[i] / lower[i])
    print("答案为 %.4f" % ans)
    # 答案为 32.6603
    

    函数章节的作业

    1

    """
    Q:
    依次从控制台输入多个整数,以整数-1作为输入结束标记,编写程序找出其中的最大数和最小数
    """
    
    x = int(input("请输入一个整数"))
    mx, mn = x, x # mx --> max, mn --> min
    while x != -1:
        mx = max(mx, x)
        mn = min(mn, x)
        # 思考下为啥放最后(因为不放最后会把 -1 也给考虑进来)
        x = int(input("请输入一个整数")) 
    print("最大值为 %d, 最小值为 %d" % (mx, mn))
    
    

    2

    """
    Q:
    利用递归函数调用方式,将所输入的5个字符,以相反顺序打印出来。
    Solution:
    稍微有点难度,没搞懂没关系
    """
    n = 5
    def rec_print(cnt):
        """
        cnt: 代表当前是第几层递归
        """
        if (cnt == 5): return
        char = input("请输入一个字符") # 接收输入
        rec_print(cnt + 1) # 直接递归到下一个元素
        print(char) # 之前的元素全部处理好之后输出
    rec_print(0)
    

    3

    """
    Q:
    编写程序将一个不确定位数的正整数进行三位分节后输出,如输入1234567,输出1,234,567。
    """
    # 法一,字符串模拟
    x = int(input("请输入一个数字"))
    if (len(str(x)) < 3): # 假如小于 3 直接切片就会越界! 意识到了嘛!
        print(x)
    else:
        print(str(x)[-3:])
    
    # 法二,数学方法
    ans = ""
    x = int(input("请输入一个数字"))
    for i in range(3):
        ans += str(x % 10) # 直接 %10 取低位
        x = x // 10 # 往右移一位, 记得整除!
    print(ans[::-1]) # 翻转
    

    4

    """
    Q:
    请分别用递归技术和迭代技术,将一个十进制正整数,以七进制形式打印在屏幕上。
    """
    # 迭代版本
    num = int(input("请输入一个数字"))
    res = 0 # 存储结果
    base = 1 # 存储基数,也就是当前第几位了 eg: 205 这个2就是 2 * 100
    while num > 0:
        t = num % 7 # 当前位的数组
        num = num // 7 # 修改num数字大小
        res += (t * base) # 更新答案
        base *= 10 # base 增加一位
    print(res)
    
    # 递归版本
    # 看不懂没关系,我到时候和猪猪讲!!!! 
    def ten2seven(cur, base):
        if (cur <= 0): return 0
        res = (cur % 7) * base
        return res + ten2seven(cur // 7, base * 10)
    num = int(input("请输入数字"))
    print(ten2seven(num, 1))
    
  • 相关阅读:
    autopoi升级到4.0版本修改方法
    JeecgBoot的前端Form升级为FormModel用法(支持 v-model 绑定)
    如何设计一张带二维码的打印报表?
    低代码概念报表-JimuReport1.1.09 版本发布
    分组报表怎么做,积木报表十分钟搞定!
    JeecgBoot 2.4.2 积木报表版本发布,基于SpringBoot的低代码平台
    低代码开发是如何解决企业招聘技术人才难题?
    JimuReport积木报表1.1.05 版本发布,免费的企业级 Web 报表工具
    Docker安装elasticsearch 7.7.0
    Jeecg 文件上传漏洞补丁说明
  • 原文地址:https://www.cnblogs.com/Last--Whisper/p/14023944.html
Copyright © 2020-2023  润新知