[Python] 慕课北京大学陈斌老师Python基础课2-7章 学习笔记


个人学习记录,如有错误欢迎指正。

数据类型

陈斌老师python课

列表归并排序

def merge_sort(lst):
    if len(lst) <= 1:
        return lst
    middle = int(len(lst) / 2)
    left = merge_sort(lst[:middle])
    right = merge_sort(lst[middle:])
    merged = []
    while left and right:
        merged.append(left.pop(0) if left[0] <= right[0] else right.pop(0))
        # left.pop(0)是提取left的第0个元素并更新left
        # 将left与right中第0位上最小的元素提取出来加到merged中
        # 若right的更小,则right的第0位被提取,下一次比较的是right的第1位和left的第0位
    merged.extend(left if left else right)
    # extend与append都是将元素添加到merged中,添加一个元素无差别
    # 若添加的为列表或元组,extend是添加列表的元素,而append是将其作为一个整体添加上
    # 在此只能用extend
    return merged


data_lst = [6, 202, 100, 301, 38, 8, 1]
print(merge_sort(data_lst))

字符串操作

s = ‘abcdefg123456’
要获得 ‘54321’

s[::-1][0:5]  # 先反转载取5个字符
s[-1:6:-1]
s[-1:-6:-1]  # 6和-6都是g,不包含g
# 步长为-1时,是从右向左取
# 故s[0:5:-1]的结果为'’(空字符串)因为它根本就没切到字符

ls.reverse()与reversed(ls)区别

  1. ls.reverse()与ls.sort() 无返回值,直接改变原列表
    若print(ls.reverse()) 返回 None
    可以先ls.reverse() 再 print(ls)

  2. reversed()与sorted()不改变原列表,有返回值
    reversed()返回一个反转的迭代器,不是列表
    sorted()返回列表

列表元素绝对值排序

输入一个列表,要求列表中的每个元素都为整数;

将列表中的所有元素按照它们的绝对值大小进行排序,绝对值相同的还保持原来的相对位置,打印排序后的列表(绝对值大小仅作为排序依据,打印出的列表中元素仍为原列表中的元素).

输入:-2 1 3
输出:[1, -2, 3]

a_list = list(map(int, input().split()))
print(sorted(a_list, key=abs))

计算与控制流

阶乘求和

给定任意正整数n,计算 1 ! + 2 ! + 3 ! + . . . + n ! 1!+2!+3!+...+n! 1!+2!+3!+...+n!的值。

解法有很多,可参考Python花式编程:6种方法计算1!+2!+…+n!.

在此列举两个:

n = int(input())
t, s = 1, 0
for i in range(1, n+1):
    t = t*i  # 不断更新t
    s += t  # 下个数的阶乘只需要在上个t的基础上再乘以此数即可
print(s)

此方法时间最少。

还可使用math库中求阶乘的函数factorial.

from math import factorial
n = int(input())
s = sum(map(factorial, range(1, n+1)))
print(s)

英文对应阿拉伯数字

给定一个英文数字字符串,打印相应阿拉伯数字字符串。
输入:one-four-five-nine
输出:1459

 str = input().split('-')
d = {
    
    'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5,\
     'six': 6, 'seven': 7, 'eight': 8, 'nine': 9, 'ten': 10, 'zero': 0}
for i in str:
    print(d.get(i), end='')

水仙花数

水仙花数是指一个n位数 (n≥3),它的每个位上的数字的n次幂之和等于它本身。

例如:153是一个“水仙花数”,因为 153 是个3位数,而 1 3 + 5 3 + 3 3 = 153 1^3+5^3+3^3=153 13+53+33=153

输入一个正整数max,输出100到max之间的所有水仙花数(包括max)

输入:2500
输出
153
370
371
407
1634

m = input()
for i in range(100, int(m)+1):
    s = list(str(i))
    n = len(s)
    su = 0
    for j in s:
        su += int(j)**n
    if su == i:
        print(i)

解法二:使用函数

def water(n):
    a = list(str(n))
    m = len(a)
    s = 0
    for i in a:
        s += int(i)**m
    return s == n


max_n = int(input())
for j in range(100, max_n+1):
    if water(j):
        print(j)

打印完数

一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如 6 = 1+2+3.

输入一个正整数n(n<1000),输出1到n之间的所有完数(包括n)。

输入:30
输出
6
28

n = int(input())
for i in range(1, n+1):
    s = []
    for j in range(1, i):
        if i % j == 0:
            s.append(j)  # 将其因子放在列表内
    if sum(s) == i:
        print(i)

打印素数

给定一个大于2的正整数n,打印出小于n(不包括n且n不大于100)的所有素数。

要求将符合条件的输出填入一个列表中,打印的结果为该列表。

输入:10
输出:[2, 3, 5, 7]

若一个数为合数,则它可分解为两个比自身小的数的乘积,其中一个比它的开方大,一个小。所以在进行第二次遍历的时候只要看小于开方的情况即可。

n = int(input())
s = []
for i in range(2, n):
    for j in range(2, int(i**0.5)+1):
        if i % j == 0:
            break
    else:
        s.append(i)
print(s)

补充
for…else与 while…else

for <循环变量> in <可迭代对象>:
    <语句块1>
    break  # 跳出循环
    continue  # 略过余下循环语句,再执行
else:  # 迭代完毕,则执行
    <语句块2>


while <逻辑表达式>:
	<语句块>
	break   # 跳出循环
	continue  # 略过余下循环语句
	<语句块>
else:  # 条件不满足退出循环,则执行
	<语句块>

最大公约数和最小公倍数

求最大公约数可用辗转相除法辗转相减法

辗转相除法

原理详见:欧几里德算法

在这里插入图片描述

def hcf(a, b):
    if a < b:
        a, b = b, a
    if a % b == 0:
        divisor = b
    else:
        divisor = hcf(b, a % b)
    return divisor


num_1 = int(input())
num_2 = int(input())
print(hcf(num_1, num_2))

辗转相减法

原理详见:更相减损法为什么可以求出两个数的最大公约数你?数学原理是什么?

在这里插入图片描述

def hcf_2(a, b):
    if a < b:
        a, b = b, a
    if a - b == 0:
        divisor = a
    else:
        divisor = hcf_2(b, a-b)
    return divisor


num_1 = int(input())
num_2 = int(input())
print(hcf_2(num_1, num_2))

最小公倍数=两数乘积/最大公约数
在这里插入图片描述
在上面程序的后边加上

multiple = num_1 * num_2 / hcf_2(num_1, num_2)
print(multiple)

或者使用原始的方法:
取出两个整数中的较大者,然后将这个数依次去除原先的两个数,如果可以整除就是最小公倍数。如果不可以,则依次加1,直至可以被两个数整除为止。

def lcm(a, b):
    if a < b:
        z = a
    else:
        z = b
    while True:
        if z % a == 0 and z % b == 0:
            multiple = z
            break
        else:
            z += 1
    return multiple


num_1 = int(input())
num_2 = int(input())
print(lcm(num_1, num_2))

求阶乘

def fact(n):
    if n == 1:
        s = 1
    else:
        s = n * fact(n-1)
    return s


m = int(input(""))
print(fact(m))

冒泡排序

冒泡排序是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

已知输入为一个列表,列表中的元素都为整数,我们定义冒泡排序函数为bubbleSort,将列表中的元素按从小到大进行排序后得到一个新的列表并输出
在这里插入图片描述

def bubble_sort(alist):
    n = len(alist)
    for i in range(n):
        for j in range(n - i - 1):
            if alist[j] > alist[j+1]:
                alist[j], alist[j+1] = alist[j+1], alist[j]
    return alist


alist = list(map(int, input().split()))
print(bubble_sort(alist))

经过i=0循环,将最大的数排到最后,比较次数为n-1;
i=1循环,将倒第二大的数排到后边,比较次数为n-2;

i= n-1循环,比较次数为1

基本扩展模块

分形数

import turtle


def tree(branch_len, t):
    if branch_len > 5:
        t.forward(branch_len)
        t.right(20)
        tree(branch_len-15, t)  # 画右边的树枝
        t.left(40)
        tree(branch_len-15, t)  # 画左边的树枝
        t.right(20)
        t.backward(branch_len)  # 回到原处


def main():
    t = turtle.Turtle()  # 生成海龟
    my_win = turtle.Screen()  # 生成画布
    t.left(90)
    t.up()
    t.backward(100)
    t.down()  # 海龟调整位置
    t.color('green')
    tree(45, t)
    my_win.exitonclick()  # 点击关闭图形窗口,避免绘制完直接关闭


main()

绘制tree(15,t)时,在终点左右转动但是没有前进,最后执行t.backward(branch_len)回到上一个节点。

判断第几天

给定年月日,如2019/1/8,打印输出这一天是该年的第几天。
输入:2019/1/8
输出:8
解法一:笨办法,自己做的

import calendar


def month_day(y, m):
    if m in [1, 3, 5, 7, 8, 10, 12]:
        d = 31
    elif m in [4, 6, 9, 11]:
        d = 30
    else:
        if calendar.isleap(y):
            d = 29
        else:
            d = 28
    return d


date = list(map(int, input().split('/')))
n = 0
for i in range(1, date[1]):
    n += month_day(date[0], i)
print(n+date[2])

解法二:网上搜的简单

from datetime import *
d = input()
d1 = datetime.strptime(d[:4]+'/1/1', '%Y/%m/%d')  # 这一年的1月1号
d2 = datetime.strptime(d, '%Y/%m/%d')  # 输入的日期
print((d2-d1).days+1)  #.days只显示天数,否则后边还有时间

特殊的数

一个特殊的正整数,它加上150后是一个完全平方数,再加上136又是一个完全平方数,求符合条件的最小的一个数。

思路:如果一个数的平方根的平方等于该数,这说明此数是完全平方数;若一个数不是完全平方数,则它开方后为小数,取整后再平方不等于原本的值

n = 1
while 1:
    if int((n+150)**0.5)**2 == (n+150) and int((n+150+136)**0.5)**2 == (n+150+136):
        print(n)
        break
    n = n + 1

大大的叉

打印出n阶的“叉”,这个叉图案由字符‘+’和‘X’构成,n越大,这个图案也就越大

输入:3
输出:
X+++X
+X+X+
++X++
+X+X+
X+++X

n = int(input())
for i in range(2*n-1):
    for j in range(2*n-1):
        if j == i or j == 2*n-1-i-1:
            print('X', end='')
        else:
            print('+', end='')
    print()

解法二:

n = int(input())
for i in range(2 * n - 1):
    l = (2 * n - 1) * ['+']
    l[i] = 'X'
    l[-1-i] = 'X'
    print("".join(l))  # 将列表转换为字符串
    # str.join(iter)是在iter变量中出最后一个元素外每个元素后增加一个str

约瑟夫环问题

已知n个人(以编号0,1,2,3…n-1分别表示)围坐在一张圆桌周围。从编号为0的人开始报数1,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

输入:两个正整数n, m,其中3<=n<=100, 1<=m<=n

输出:按照顺序出列的人的编号列表

思路:详细请见约瑟夫环问题递归解法的一点理解.

代码是按照思路自己改的,有错误欢迎指正

def ysf(a, b, c):  # a为总人数,b为最大报到数,c为第c次出列
    if c == 1:
        a_list = (a + b - 1) % a
    else:
        a_list = (ysf(a-1, b, c-1) + b) % a
    return a_list


n = int(input())
m = int(input())
List = []
for i in range(n):  # 循环n次后,圆桌的人才能全部出列
    List.append(ysf(n, m, i+1))  # i本来从0开始,第一次出列要在原来基础上+1
print(List)

猜你喜欢

转载自blog.csdn.net/weixin_43429677/article/details/107524001