Week 4:函数打印上下三角、三大排序和递归

一、上三角
这里写图片描述

1、方法一:基本方法,前面空格、后面数字,定好 n 后,每行宽度即定,再依据 j 自身宽度控制空格

#弊端:虽然能打印整齐,但每次都要根据j的位数计算一次空格的个数,即' '*len(str(j))

def triangle(n):
    for i in range(1,n+1):
        for j in range(n,0,-1):
            if j>i:
                print(' '*len(str(j)),end=' ')
            else:
                print(j,end=' ')
        print()
        
triangle(12)

2、方法二:对齐方式;右对齐,最大宽度以最后一行为准

#两层循环,tail为最后一行的字符串

def triangle(n):
    tail=' '.join(str(i) for i in range(n,0,-1))
    length=len(tail)
    for i in range(1,n):
        print('{:>{}}'.format(' '.join(str(j) for j in range(i,0,-1)),length))
    print(tail)
        
triangle(12)

3、方法三:利用方法二的 tail 字符串结果切片打印,切片的起始端开始是 -1,每逢10的整数次幂、起始端左移的长度加1

def triangle(n):
    tail=' '.join(str(i) for i in range(n,0,-1))
    length=len(tail)
    s={10**i for i in range(1,length)}
    start=1
    step=2
    for i in range(1,n):
        start-=step
        print('{:>{}}'.format(tail[start:],length))
        if i+1 in s:
            step+=1
    print(tail)

triangle(12)

4、方法四:对方法二的改进,将字符串换成列表,打印时用一个 for 循环,辅以列表切片

def triangle(n):
    tail=[str(i) for i in range(n,0,-1)]
    length=len(' '.join(tail))
    for i in range(1,n+1):
        print('{:>{}}'.format(' '.join(tail[n-i:]),length))
        
triangle(12)

5、方法五:对 tail 字符串切片打印,转折点为索引处出现空格,format 右对齐

def triangle(n):
    tail=' '.join(str(i) for i in range(n,0,-1))
    length=len(tail)
    for i in range(length):
        if tail[-i] == ' ':
            print('{:>{}}'.format(tail[-i+1:],length))
    print(tail)

triangle(12)

二、下三角
这里写图片描述

1、方法一:对 tail 字符串切片打印,转折点为索引处出现空格,打印空格以对齐

def triangle2(n):
    tail=' '.join(str(i) for i in range(n,0,-1))
    print(tail)
    for i in range(len(tail)):
        if tail[i] == ' ':
            print(' '*i,tail[i+1:])

triangle2(12)

总结:
1、计算好最长的一行,其它行均利用该结果进行切片操作,最省空间,时间上只用一层循环,且每次循环用索引找值,减少计算;
2、相比于打印空格使格式整齐,提前算好最大宽度再用 format 函数右对齐更便利

三、冒泡排序、选择排序、插入排序的汇总

1、冒泡排序

import random
l=[random.randint(1,20) for _ in range(10)]
print(l)

for i in range(len(l)-1):
    swap_count=0
    for j in range(len(l)-1-i):
        if l[j]>l[j+1]:
            l[j],l[j+1]=l[j+1],l[j]
            swap_count+=1
    if swap_count==0:
        break
print(l)

2、选择排序

import random
l=[random.randint(1,20) for _ in range(10)]
print(l)

for i in range(len(l)-1):
    small=i
    for j in range(i+1,len(l)):
        if l[small]>l[j]:
            small=j
    l[small],l[i]=l[i],l[small]
print(l)

3、插入排序

import random
l=[random.randint(1,20) for _ in range(10)]
print(l)

l=[0]+l
for i in range(2,len(l)):
    l[0]=l[i]
    while l[0]<l[i-1]:
        l[i-1],l[i]=l[i],l[i-1]
        i-=1
    l[i]=l[0]
print(l[1:])

四、递归

1、斐波那契数列

#原始版本,每一条分支都没有利用到之前的计算结果

def fib(n):
    if n<3:
        return 1 
    else:
        return fib(n-1)+fib(n-2)
#优化:利用到上次的计算结果

def fib(n,pre=0,cur=1):
    pre,cur = cur,pre+cur
    if n==1:
        return pre 
    else:
        return fib(n-1,pre,cur)

print(fib(5))
#参数可直接提到形参中

def fib(n,pre=0,cur=1):
    if n==1:
        return cur 
    else:
        return fib(n-1,cur,pre+cur)

print(fib(5))
#  面向对象方法,利用上次缓存结果

class Fib:
    def __init__(self):
        # 使用缓存,减少计算
        self.items=[0,1,1]

    def __call__(self,index):
        if index>=len(self.items):
            for i in range(len(self)+1,index+1):
                self.items.append(self.items[i-1]+self.items[i-2])
        return self.items[index]

    def __getitem__(self,index):
        return self(index)

    # 获取长度
    def __len__(self):
        return len(self.items)-1

    # 解决迭代问题,把fib对象当可迭代对象
    def __iter__(self):
        return iter(self.items)


fib=Fib()
# 虽然内部都是用call方法实现,但调用的意义完全不同
print(fib(5))  # 把实例当可调用实例来看
print(fib[5])  # 把实例当可索引的list或dict来用

for x in fib:
    print(x)

2、求阶乘

#基本形式

def fac(n):
    if n==1:
        return 1 
    else: 
        return n*fac(n-1)
#传参形式

def fac(n,f=1):
    if n==1:
        return f
    else: 
        return fac(n-1,f*n)

3、猴子吃桃

def peach(d=10,s=1):
    if d==1:
        return s
    else: 
        return peach(d-1,2*(s+1))

print(peach())

4、将一个数逆序放到列表中,1234 -> [ 4,3,2,1]

#递归切片,方法一

def unlist(n,l=[]):
    l.append(n[-1])
    if len(n)==1:
        return l
    else:
        return unlist(n[:-1],l)

print(unlist('1234'))
#递归切片,方法二

def unlist(n,l=[]):
    if n:
        l.append(n[-1])
        return unlist(n[:-1])
    else:
        return l

print(unlist('1234'))
#递归切片,方法三,在循环中反复递归调用,循环结束、临界条件一个return,然后从内往外每一个函数调用都结束并return l,直至最外层,而l都是相同的

def unlist(n,l=[]):
    if n:
        l.append(n[-1])
        unlist(n[:-1])
    return l

print(unlist('1234'))
#数字整除方法

def unlist(n,l=[]):
    n,s=divmod(n,10)
    l.append(s)
    if n==0:
        return l
    else: 
        return unlist(n,l)

print(unlist(1234))

5、字典扁平化
src:{‘a’:{‘b’:1,‘c’:2},‘d’:{‘e’:3,‘f’:{‘g’:4}}}
dst:{‘a.b’:1,‘a.c’:2,‘d.e’:3,‘d.f.g’:4}
这种字典一般深度也有限,故本题的考点为递归

正错代码示例:

x={'a':{'b':1,'c':2},'d':{'e':3,'f':{'g':4}}}
d1={}

#错误flatmap
def flatmap(src,newkey=''):
    for k,v in src.items():
        if isinstance(v,dict):
            newkey=newkey+k+'.'   #
            flatmap(v,newkey)
        else:
            d1[newkey+k]=v
    return d1
print(flatmap(x))

#修改后
d2={}
def flatmap2(dic, newkey=''):
    for k, v in dic.items():
        if isinstance(v,dict):
            flatmap2(v,newkey+k +'.')  #
        else:
            d2[newkey+k] = v
    return d2
print(flatmap2(x))

#运行结果为
{'a.b': 1, 'a.c': 2, 'a.d.e': 3, 'a.d.f.g': 4}
{'a.b': 1, 'a.c': 2, 'd.e': 3, 'd.f.g': 4}

从内到外,对于引用类型,return的都是堆里的对象地址

也可对函数做一些调整

#把d={}放到形参里,而不是放在全局

x={'a':{'b':1,'c':2},'d':{'e':3,'f':{'g':4}}}

def flatmap(src, newkey='',d={}):
    for k, v in src.items():
        if isinstance(v,dict):
            flatmap(v,newkey+k +'.')
        else:
            d[newkey+k] = v
    return d
print(flatmap(x))
#改成嵌套函数,内层函数依然可以递归调用

x={'a':{'b':1,'c':2},'d':{'e':3,'f':{'g':4}}}

def flatmap(src):
    d={}
    def _flatmap(src, newkey=''):
        for k, v in src.items():
            if isinstance(v,dict):
                _flatmap(v,newkey+k +'.')
            else:
                d[newkey+k] = v
    _flatmap(src)
    return d
print(flatmap(x))

猜你喜欢

转载自blog.csdn.net/weixin_42196568/article/details/81911082