1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 4.Python数据结构与算法分析课后习题__chapter4

4.Python数据结构与算法分析课后习题__chapter4

时间:2020-03-10 09:14:44

相关推荐

4.Python数据结构与算法分析课后习题__chapter4

chpter4_answer

一、讨论题二、编程练习1.写一个递归函数来计算数的阶乘。2.写一个递归函数来反转列表。3.采用下列一个或全部方法修改递归树程序。4.找到一种绘制分形山的算法。提示:可以使用三角形。5.写一个递归函数来计算斐波那契数列,并对比递归函数与循环函数的性能。6.实现汉诺塔问题的一个解决方案,使用3个栈来记录盘子位置。7.使用turtle绘图模块写一个递归程序,画出希尔伯特曲线 。8.使用turtle绘图模块写一个递归程序,画出科赫雪花。9.写一个程序来解决这样一个问题:有2个坛子,其中一个的容量是4加仑,另一个的是3加仑。坛子上都没有刻度线。可以用水泵将它们装满水。如何使用4加仑的坛子最后装有2加仑的水?10.扩展练习9中的程序,将坛子的容量和较大的坛子中最后的水量作为参数。11.写一个程序来解决这样一个问题:3个羚羊和3只狮子准备乘船过河,河边有一艘能容纳2只动物的小船。但是,如果两侧河岸上的狮子数量大于羚羊数量,羚羊就会被吃掉。找到运送办法,使得所有动物都能安全渡河。12.利用turtle绘图模块修改汉诺塔程序,将盘子的移动过程可视化。提示:可以创建多只小乌龟,并将它们的形状改为长方形。13. 打印帕斯卡三角形(杨辉三角)。14.假设一个计算机科学家兼艺术大盗闯入美术馆。他只能用一个容量为W磅的背包来装盗取的艺术品,并且他对每一件艺术品的价值和重量了如指掌。他会如何写一个动态规划程序来帮助自己最大程度地获利呢?下面的例子可以帮助你思考:假设背包容量是20磅,艺术品为5件。15.请尝试解决字符串编辑距离问题,它在很多研究领域中非常有用。假设要把单词algorithm转换成alligator。对于每一个字母,可以用5个单位的代价将其从一个单词复制到另一个,也可以用20个单位的总代价将其删除或插入。拼写检查程序利用将一个单词转换为另一个的总代价来提供拼写建议。请设计一个动态规划算法,给出任意两个单词之间的最小编辑距离。三、总结

参考链接:

/Morbidmuse/article/details/119641686 link

/fhlsyol/article/details/106439254 link

/p/80682302link

一、讨论题

略略略。

二、编程练习

1.写一个递归函数来计算数的阶乘。

def Factorial(n):if n == 1:return 1else:return n * Factorial(n-1)if __name__ == '__main__':print(Factorial(3))

2.写一个递归函数来反转列表。

def reverse(alist):if len(alist) == 1:return alist[0]elif len(alist) == 2:alist[0], alist[1] = alist[1], alist[0]return alistelse:return [alist[-1]] + reverse(alist[:-1])if __name__ == '__main__':testlist = [1, 2, 3, 4, 5]print(reverse(testlist))

3.采用下列一个或全部方法修改递归树程序。

修改树枝的粗细程度,使得branchLen越小,线条越细。修改树枝的颜色,使得当branchLen非常小时,树枝看上去像叶子。修改小乌龟的转向角度,使得每一个分支的角度都是一定范围内的随机值,例如使角度取值范围是15~45度。运行程序,查看绘制结果。递归地修改branchLen,使其减去一定范围内地随机值,而不是固定值。

如果实现上述所有改进方法,绘制出地树将十分真实。

结果如图:

(有点小丑,说好地十分真实呢……)

from turtle import *import randomt = Turtle()tWin = t.getscreen()def tree(branchLen, t):t.speed(100)if branchLen> 5:t.width(50 * branchLen / 110)if branchLen > 10:t.color('black')else:t.color('green')t.forward(branchLen)t.right(20)tree(branchLen-random.randrange(10, 21), t)t.left(40)tree(branchLen-random.randrange(5, 16), t)t.right(20)t.backward(branchLen)if __name__ == '__main__':t.left(90)t.up()t.backward(300)t.down()t.color('green')tree(110, t)tWin.exitonclick()

4.找到一种绘制分形山的算法。提示:可以使用三角形。

参考:/Morbidmuse/article/details/119641686

from turtle import *import randomdef drawTriangle(points, color, myTurtle):myTurtle.color(color)myTurtle.up()myTurtle.goto(points[0])myTurtle.down()myTurtle.begin_fill()myTurtle.goto(points[1])myTurtle.goto(points[2])myTurtle.goto(points[0])myTurtle.end_fill()def mountain(t, start_x, start_y, end_x, end_y, depth, color):y_offset = random.randint(10, 30)mid_x = (start_x + end_x) / 2mid_y = (start_y + end_y) / 2 + y_offsetdrawTriangle([(start_x, start_y),(end_x, end_y),(mid_x, mid_y)], color, t)if depth > 0:mountain(t, start_x, start_y, mid_x, mid_y, depth - 1, color)mountain(t, mid_x, mid_y, end_x, end_y, depth - 1, color)if __name__ == '__main__':myTurtle = Turtle()myTurtle.speed(20)myWin = myTurtle.getscreen()x1, y1, x2, y2 = -400, -50, 400, -50colors = ['#DAE0DF', '#959998', '#505453', '#070707']for i in range(4):mountain(myTurtle, x1, y1 - i * 30, x2, y2 - i * 30, 6, colors[i])myWin.exitonclick()

5.写一个递归函数来计算斐波那契数列,并对比递归函数与循环函数的性能。

import datetimedef Fibonacci_recursion(n):if n == 1 or n == 2:return 1else:return Fibonacci_recursion(n - 1) + Fibonacci_recursion(n - 2)def Fibonacci_cir(n):n1, n2 = 1, 1for i in range(n - 1):n1, n2 = n2, n1 + n2return n1if __name__ == '__main__':t1 = datetime.datetime.now()print(Fibonacci_recursion(35))t2 = datetime.datetime.now()print('Fibonacci_recursion need time:', t2 - t1)t3 = datetime.datetime.now()print(Fibonacci_cir(35))t4 = datetime.datetime.now()print('Fibonacci_circulate need time:', t4 - t3)

结果如图:

由结果知:能够用递归解决问题不代表递归就是最优解。

6.实现汉诺塔问题的一个解决方案,使用3个栈来记录盘子位置。

代码有点臃肿,因为我想把每一步的栈也就是盘子的位置打印出来,这样看起来更直观。

结果如图:

from chapter3.stack import Stackleft = Stack()mid = Stack()right = Stack()HEIGHT = 5i = HEIGHTwhile i > 0:left.push(i)i -= 1print("Initial: height = %d" % HEIGHT)print('left', left.items)print('mid', mid.items)print('right', right.items)def moveTower(height, fromPole, toPole, withPole):if height >= 1:moveTower(height-1, fromPole, withPole, toPole)moveDisk(fromPole, toPole)moveTower(height-1, withPole, toPole, fromPole)def moveDisk(fp, tp):print("-----------------------------")print("moving disk from", fp, "to", tp)if fp == 'p1' and tp == 'p2':if not left.isEmpty():mid.push(left.pop())print('left', left.items)print('mid', mid.items)print('right', right.items)elif fp == 'p1' and tp == 'p3':if not left.isEmpty():right.push(left.pop())print('left', left.items)print('mid', mid.items)print('right', right.items)elif fp == 'p2' and tp == 'p1':if not mid.isEmpty():left.push(mid.pop())print('left', left.items)print('mid',mid.items)print('right',right.items)elif fp == 'p2' and tp == 'p3':if not mid.isEmpty():right.push(mid.pop())print('left', left.items)print('mid',mid.items)print('right',right.items)elif fp == 'p3' and tp == 'p1':if not right.isEmpty():left.push(mid.pop())print('left', left.items)print('mid',right.items)print('right',right.items)else:if not right.isEmpty():mid.push(right.pop())print('left', left.items)print('mid',mid.items)print('right',right.items)if __name__ == '__main__':moveTower(HEIGHT, 'p1', 'p3', 'p2')

7.使用turtle绘图模块写一个递归程序,画出希尔伯特曲线 。

结果如图:

from turtle import *t = Turtle()tWin = t.getscreen()def hilbert(level, angle, step):if level == 0:passelse:t.right(angle)hilbert(level - 1, -angle, step)t.forward(step)t.left(angle)hilbert(level - 1, angle, step)t.forward(step)hilbert(level - 1, angle, step)t.left(angle)t.forward(step)hilbert(level - 1, -angle, step)t.right(angle)if __name__ == '__main__':t.up()t.backward(300)t.left(90)t.backward(300)t.down()t.speed(50)hilbert(5, 90, 10)tWin.exitonclick()

8.使用turtle绘图模块写一个递归程序,画出科赫雪花。

结果如图:

from turtle import *t = Turtle()tWin = t.getscreen()def koch(size, level):if level == 0:t.fd(size)else:for i in [0, 60, -120, 60]:t.left(i)koch(size/3, level-1)if __name__ == '__main__':t.speed(50)level = 4t.penup()t.goto(-250, 150)t.pensize(2)t.pendown()koch(500, level)t.right(120)koch(500, level)t.right(120)koch(500, level)t.right(120)tWin.exitonclick()

9.写一个程序来解决这样一个问题:有2个坛子,其中一个的容量是4加仑,另一个的是3加仑。坛子上都没有刻度线。可以用水泵将它们装满水。如何使用4加仑的坛子最后装有2加仑的水?

&

10.扩展练习9中的程序,将坛子的容量和较大的坛子中最后的水量作为参数。

结果如图:

from chapter3.stack import Stacks1 = Stack()s2 = Stack()def solution(a, b, c):for i in range(b):s2.push('water')print('----------------------------------------------------')print('Initial')print('s1:', s1.items)print('s2:', s2.items)for i in range(a):s1.push(s2.pop())print('----------------------------------------------------')print('from s2 to s1:')print('s1:', s1.items)print('s2:', s2.items)if not s2.size() == c:for i in range(a):s1.pop()print('----------------------------------------------------')print('drop s1:')print('s1:', s1.items)print('s2:', s2.items)s1.push(s2.pop())return solution(2 * a - b, b, c)else:print('----------------------------------------------------')return 'comleted'# a,b,c=small,big,targetprint(solution(3, 4, 2))

11.写一个程序来解决这样一个问题:3个羚羊和3只狮子准备乘船过河,河边有一艘能容纳2只动物的小船。但是,如果两侧河岸上的狮子数量大于羚羊数量,羚羊就会被吃掉。找到运送办法,使得所有动物都能安全渡河。

参考链接:/fhlsyol/article/details/106439254link(ps:这个代码的输出结果含义是小船每次一来一回载的动物)

搜了一下过河问题大多都是用图解决,还没复习到,先插个眼回头看。

from collections import Counterfrom random import sample, randintclass Solution:"""解决问题的方案类"""def __init__(self):"""初始化属性"""self.left = ['羚羊'] * 3 + ['狮子'] * 3 # 后面用到了Counter,所以这里可以用字符串表示,不用0,1表示,更直观一点self.left_checkpoint = [] # 左边的存档,用于试错后恢复self.right = []self.right_checkpoint = []self.result = [[]] # 结果,给个初始值是为了避免out of index的情况,取结果的时候切片即可self.result_checkpoint = []self.r_direction = True # True为右,False为左def go(self):"""渡河"""if self.r_direction: # 向右渡河boat = sample(self.left, 2)for i in boat:self.left.remove(i)self.right.append(i)else: # 向左渡河if len(self.right) > 1: # 这里判断是为了避免sample取的时候越界(从1个里面取2个)boat = sample(self.right, randint(1, 2))else:boat = sample(self.right, 1)for i in boat:self.right.remove(i)self.left.append(i)return boatdef judge(self):"""判断"""if self.left and self.right:left_counter = Counter(self.left)right_counter = Counter(self.right)if (left_counter['羚羊'] and left_counter['羚羊'] < left_counter['狮子']) or \(right_counter['羚羊'] and right_counter['羚羊'] < right_counter['狮子']):return Falsereturn Truedef checkpoint(self):"""检查点"""self.left_checkpoint, self.right_checkpoint, self.result_checkpoint = \self.left.copy(), self.right.copy(), self.result.copy()def reset(self):"""读档"""self.left, self.right, self.result = \self.left_checkpoint.copy(), self.right_checkpoint.copy(), self.result_checkpoint.copy()def get_result(self):"""模拟渡河过程,获取结果"""while len(self.right) < 6:self.checkpoint() # 存档boat = self.go() # 渡河boat.sort()if self.judge() and boat != self.result[-1]: # 这里判断是为了避免相同的人来回的情况,以求尽可能少的解self.r_direction = not self.r_direction # 调转船头self.result.append(boat)else:self.reset() # 读档return self.result[1:]def main():"""主函数"""repeat = 10000 # 重复执行次数result_set = set() # 解的集合solution = Solution()for _ in range(repeat):result = solution.get_result()result_set.add(str(result))solution.__init__()print(f'经{repeat}次执行,共得到{len(result_set)}种不同的结果,结果如下:', end='\n\n')for result in result_set:print(result)if __name__ == '__main__':main()

12.利用turtle绘图模块修改汉诺塔程序,将盘子的移动过程可视化。提示:可以创建多只小乌龟,并将它们的形状改为长方形。

结果如下:

from turtle import *t = Turtle()global t1, t2, t3height = 5color = ["red", "orange", "yellow","green", "blue","purple", "pink", "black", 'gray']# 圆盘class Disc(Turtle):def __init__(self, n):Turtle.__init__(self, shape="square", visible=False)self.pu()# 矩形大小self.shapesize(1.5, n*1.5, 2) # square-->rectangle# 设置颜色# self.fillcolor(n / height, 0, 1 - n / height)self.fillcolor(color[n-1])self.st()self.speed(5)class Tower(list):"Hanoi tower, a subclass of built-in type list"def __init__(self, x):"create an empty tower. x is x-position of peg"self.x = x# 加入盘子def push(self, d):d.setx(self.x)d.sety(-150+34*len(self))self.append(d)# 取出盘子def pop(self):d = list.pop(self)d.sety(150)return ddef moveTower(height, fromPole, toPole, withPole):if height >= 1:moveTower(height-1, fromPole, withPole, toPole)toPole.push(fromPole.pop())moveTower(height-1, withPole, toPole, fromPole)def play():onkey(None,"space")clear()try:moveTower(height, t1, t3, t2)write("press STOP button to exit",align="center", font=("Courier", 16, "bold"))except Terminator:pass # turtledemo user pressed STOPdef DrawPoles():'''画三个柱子'''t.speed(0)t.up()t.left(90)t.pensize(10)DrawOnePole(-250, -200)DrawOnePole(0, -200)DrawOnePole(250, -200)def DrawOnePole(x, y):'''画一个柱子'''t.goto(x, y)t.down()t.fd(300)t.up()if __name__ == '__main__':t1 = Tower(-250)t2 = Tower(0)t3 = Tower(250)ht()penup()goto(0, -225)DrawPoles()for i in range(height,0,-1):t1.push(Disc(i))# prepare spartanic user interface ;-)write("press spacebar to start game",align="center", font=("Courier", 16, "bold"))onkey(play, "space")listen()mainloop()

13. 打印帕斯卡三角形(杨辉三角)。

帕斯卡三角形由数字组成,其中的数字交错摆放,使得

anr=n!r!(n−r)!a_{nr}=\frac{n!}{r!(n-r)!} anr​=r!(n−r)!n!​

这是计算二项式系数的等式。在帕斯卡三角形中,每个数等于其上方两数之和,如下所示。

将行数作为参数,写一个输出帕斯卡三角形的程序。

def Pascal_triangle(input_num):list = [] # an empty listfor n in range(input_num):list.append([])list[n].append(1)for m in range(1, n):list[n].append(list[n - 1][m - 1] + list[n - 1][m])list[n].append(1)for n in range(input_num):print(" " * (input_num - n), end=" ", sep=" ")for m in range(0, n + 1):print('{0:5}'.format(list[n][m]), end=" ", sep=" ")print( )if __name__ == '__main__':height = 5Pascal_triangle(height)

14.假设一个计算机科学家兼艺术大盗闯入美术馆。他只能用一个容量为W磅的背包来装盗取的艺术品,并且他对每一件艺术品的价值和重量了如指掌。他会如何写一个动态规划程序来帮助自己最大程度地获利呢?下面的例子可以帮助你思考:假设背包容量是20磅,艺术品为5件。

def dpMaxValue(objectsValueDic, weights, maxValue, objectsUsed):for weight in range(weights + 1):nowValue = objectsValueDic[0]newWeight = 0for j in [c for c in objectsValueDic.keys() if c <= weight]:if maxValue[weight - j] + objectsValueDic[j] > nowValue:nowValue = maxValue[weight - j] + objectsValueDic[j]newWeight = jmaxValue[weight] = nowValueobjectsUsed[weight] = newWeightreturn maxValue[weights]def printWeight(objectsUsed, weights):weight = weightsout = []while weight > 0:thisWeight = objectsUsed[weight]if thisWeight == 0:breakout.append(thisWeight)weight -= thisWeightprint('weights:',out)if __name__ == '__main__':objectsValueDic = {0 : 0, 2 : 3, 3 : 4, 4 : 8, 5 : 8, 9 : 10}weights = 20objectsUsed = [0] * (weights+1)print('value :',dpMaxValue(objectsValueDic, weights, [0] * (weights+1), objectsUsed))printWeight(objectsUsed, weights)

15.请尝试解决字符串编辑距离问题,它在很多研究领域中非常有用。假设要把单词algorithm转换成alligator。对于每一个字母,可以用5个单位的代价将其从一个单词复制到另一个,也可以用20个单位的总代价将其删除或插入。拼写检查程序利用将一个单词转换为另一个的总代价来提供拼写建议。请设计一个动态规划算法,给出任意两个单词之间的最小编辑距离。

参考链接:/p/80682302link

写的非常好~👍

btw,本题中用20个单位的总代价将其删除或插入可以理解为(存疑):将alligator复制到algorithm为algorithmalligator,从中再删除algorithm变成alligator共走了20step,那么用5个单位的代价将其从一个单词复制到另一个怎么理解???????😥有没有小伙伴探讨一下

def minDistance(s1, s2):memo = dict()def dp(i, j):if (i, j) in memo:return memo[(i, j)]# base caseif i == -1: return j + 1if j == -1: return i + 1if s1[i] == s2[j]:memo[(i, j)] = dp(i - 1, j - 1) # 啥都不做else:memo[(i, j)] = min(dp(i, j - 1) + 1, # 插入dp(i - 1, j) + 1, # 删除dp(i - 1, j - 1) + 1 # 替换)return memo[(i, j)]# i,j 初始化指向最后一个索引return dp(len(s1) - 1, len(s2) - 1)if __name__ == '__main__':s1 = 'algorithm's2 = 'alligator'print(minDistance(s1, s2))

三、总结

主要学习了递归(!=最优解),turtle绘图模块,动态规划等。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。