数据结构与算法 Python语言实现 第一章练习
Posted xiaomingyang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法 Python语言实现 第一章练习相关的知识,希望对你有一定的参考价值。
说明:部分代码参考了Harrytsz的文章:https://blog.csdn.net/Harrytsz/article/details/86645857,如果大家阅读时有更好的解法,欢迎沟通交流,共同进步!
巩固
R-1.1 编写一个Python函数 is_multiple(n, m),用来接收两个整数值 n 和 m,如果 n 是 m 的倍数,即存在整数 i 使得 n = mi,那么函数返回 True,否则返回 False.
R-1.2 编写一个Python函数 is_even(k),用来接收一个整数 k,如果 k 是偶数返回 True,否则返回 False。但是,函数中不能使用乘法、除法或取余操作.
R-1.3 编写一个Python函数 minmax(data),用来在数的序列中找出最小数和最大数,并以一个长度为 2 的元组的形式返回。注意:不能通过内置函数 min 和 max 来实现。
R-1.4 编写一个Python函数,用来接收正整数 n,返回 1 ~ n 的平方和。
R-1.5 基于Python的解析语法和内置函数 sum,写一个单独的命令来计算练习R-1.4中的和。
R-1.6 编写一个Python函数,用来接收正整数n,并返回 1 ~ n 中所有的奇数的平方和。
R-1.7 基于Python的解析语法和内置函数 sum,写一个单独的命令来计算练习R-1.6中的和。
R-1.8 Python 允许负整数作为序列的索引值,如一个长度为 n 的字符串 s,当索引值 -n ≤≤ k < 0 时,所指的元素为 s[k],那么求一个正整数索引值 j ?? 0,使得 s[j] 指向的也是相同的元素。
R-1.9 要生成一个值为 50, 60, 70, 80 的排列,求 range构造函数的参数.
R-1.10 要生成一个值为 8, 6, 4, 2, 0, -2, -4, -6, -8 的排列,求 range 构造函数中的参数。
R-1.11 演示怎样使用 Python 列表解析语法来产生列表 [1, 2, 4, 8, 16, 32, 64, 128, 256].
R-1.12 Python 的 random 模块包括一个函数 choice(data),可以从一个非空序列返回一个随机元素。Random模块还包含一个更基本的 randrange 函数,参数化类似于内置的 range 函数,可以在给定范围内返回一个随机数。只使用 randrange 函数,实现自己的 choice 函数。
1 # R-1.1 2 def is_multiple(n: int, m: int): 3 quotient = n / m 4 remainder = n % m 5 if quotient > 1 and remainder == 0: 6 return True 7 else: 8 return False 9 10 11 # 更优解 12 def is_multiple(n, m): 13 return n % m == 0 14 15 16 print(is_multiple(4, 2)) 17 18 19 # R-1.2 20 def is_even(k: int): 21 i = 0 22 while i < k: 23 if i + i == k: 24 return True 25 i += 1 26 return False 27 28 29 # 更优解 30 def is_even(k): 31 k = abs(k) 32 while k > 1: 33 k -= 2 34 return k == 0 35 36 37 print(is_even(5)) 38 39 40 # R-1.3 41 def minmax(data): 42 i = a = data[0] 43 for n in range(len(data)): 44 if i > data[n]: 45 i = data[n] 46 if a < data[n]: 47 a = data[n] 48 return i, a 49 50 51 # 更优解 52 def minmax(data): 53 54 minv = data[0] 55 maxv = data[0] 56 for item in data: 57 if minv > item: 58 minv = item 59 if maxv < item: 60 maxv = item 61 return minv, maxv 62 63 64 l = [1, 3, 4, 5, 8, 2, 0] 65 print(minmax(l)) 66 67 68 # R-1.4 69 def sum_square(n): 70 sum_num = 0 71 for i in range(n+1): 72 sum_num += i**2 73 print(sum_num) 74 75 76 sum_square(4) 77 78 79 # R-1.5 80 def sum_of_square2(n): 81 return sum(i**2 for i in range(n+1)) 82 83 84 def sum_of_square3(n): 85 return sum(list(map(lambda x: x**2, range(n+1)))) 86 87 88 print(sum_of_square3(3)) 89 90 91 # R-1.6 92 def odd_square(n): 93 odd_square_sum = 0 94 for i in range(1, n+1): 95 if i % 2: 96 odd_square_sum += i**2 97 return odd_square_sum 98 99 100 print(odd_square(5)) 101 102 103 # R-1.7 104 n = 5 105 print(sum(i**2 for i in range(n+1) if i % 2)) 106 107 108 # R-1.8 109 j = n+k 110 111 112 # R-1.9 113 print(list(range(50, 81, 10))) 114 115 116 # R-1.10 117 l = list(range(8, -9, -2)) 118 print(l) 119 120 121 # R-1.11 122 # 常规解法 123 i = 1 124 l = [] 125 j = 0 126 while j < 9: 127 l.append(i) 128 i *= 2 129 j += 1 130 print(l) 131 132 # 列表解析式 133 l = [i for i in range(1, 257) if 256 % i == 0] 134 135 136 # 更优解 137 l6 = list(map(lambda i: 2**i, range(9))) 138 l7 = [2 ** x for x in range(9)] 139 print(l7) 140 141 142 # R-1.12 143 from random import randrange 144 145 146 def my_choice(data): 147 while True: 148 r = randrange(min(data), max(data)+1) 149 if r in data: 150 return r 151 else: 152 continue 153 154 155 # 更优解 156 def my_choice(data): 157 myrandint = randrange(len(data)) 158 return data[myrandint] 159 160 161 l = [1, 2, 4, 6, 18, 7] 162 print(my_choice(l))
创新
C-1.13 编写一个函数的伪代码描述,该函数用来逆置 n 个整数的列表,使这些以相反的顺序输出,并将该方法与可以实现相同功能的 Python 函数进行比较。
C-1.14 编写一个 Python 函数,用来接收一个整数序列,并判断该序列中是否存在一对乘积是奇数的互不相同的数。
C-1.15 编写一个 Python 函数,用来接收一个数字序列,并判断是否所有数字都互不相同。
C-1.16 在1.5.1节 scale 函数的实现中,循环体内执行的命令 data[j] *= factor。我们已经说过这个数字类型是不可变的,操作符 *= 在这种背景下使用是创建一个新的实例(而不是现有实例的变化)。那么 scale 函数是如何实现改变调用者发送的实际参数呢?
C-1.17 1.5.1节 scale 函数的实现如下。它能正常工作吗?请给出原因。
C-1.18 演示如何使用 Python 列表解析语法来产生列表 [0, 2, 6, 12, 20, 30, 42, 56, 72, 90]。
C-1.19 演示如何使用 Python 列表解析语法在不输入所有 26 个英文字母的情况下产生列表 [‘a’, ‘b’, ‘c’,…, ‘z’]。
C-1.20 Python 的 random 模块包括一个函数 shuffle(data),它可以接受一个元素的列表和一个随机的重新排列元素,以使每个可能的序列发生概率相等。 random 模块还包括一个更基本的函数 randint(a, b),它可以返回一个 a 到 b (包括两个端点)的随机整数。只使用 randint 函数,实现自己的 shuffle 函数。
C-1.21 编写一个Python程序,反复从标准输入读取一行直到抛出 EOFError 异常,然后以相反的顺序输出这些行(用户可以通过键按 Ctrl + D 结束输入)。
C-1.22 编写一个Python程序,用来接收长度为 n 的两个整型数组 a 和 b 并返回数组 a 和 b 的点积。也就是返回一个长度为 n 的数组 c,即 c[i] = a[i] ⋅⋅ b[i], for i = 0, …, n-1.
C-1.23 给出一个 Python 代码片段的例子,编写一个索引可能越界的元素列表。如果索引越界,程序应该捕获异常结果并打印以下错误消息:“Don’t try buffer overflow attacks in Python!”
C-1.24 编写一个 Python 函数,计算所给字符串中元音字母的个数。
C-1.25 编写一个 Python函数,接收一个表示一个句子的字符串 s,然后返回该字符串的删除了所有标点符号的副本。例如, 给定字符串 “Let’s try, Mike.”,这个函数将返回 “Lets try Mike”。
C-1.26 编写一个程序,需要从控制台输入 3 个整数 a、b、c,并确定它们是否可以在一个正确的算术公式(在给定的顺序)下成立,如“a + b = c” “a = b - c” 或 “a * b = c”。
C-1.27 在 1.8 节中,我们对于计算所给整数的因子时提供了 3 种不同的生成器的实现方法。 1.8 节末尾处的第三种方法是最有效的,但我们注意到,它没有按递增顺序来产生因子。修改生成器,使得其按递增顺序来产生因子,同时保持其性能优势。
C-1.28 在 n 维空间定义一个向量 v=(v1,v2,...,vn)v=(v1?,v2?,...,vn?) 的 p 范数, 如下所示:
∣∣v∣∣=vp1+vp2+⋅⋅⋅+vpn−−−−−−−−−−−−−−√p∣∣v∣∣=p√v1p?+v2p?+⋅⋅⋅+vnp??
对于 p = 2 的特殊情况,这就成了传统的欧几里得范数,表示向量的长度。例如,一个二维向量坐标为 (4,3) 的欧几里得范数为 √4²+3²=√16+9=√25=5。编写 norm 函数,即 norm(v, p),返回向量 v 的 p 范数的值, norm(v),返回向量 v 的欧几里得范数。你可以假定 v 是一个数字列表。
1 import re 2 from random import shuffle, randint 3 4 5 # C-1.13 6 def my_reverse(data): 7 new_data = [] 8 for i in range(len(data)-1, -1, -1): 9 new_data.append(data[i]) 10 return new_data 11 12 13 # 更优解 14 def my_reverse(data): 15 return data[::-1] 16 17 18 l = [1, 2, 3, 5, 6] 19 new_l = my_reverse(l) 20 print(new_l) 21 l.reverse() 22 print(l) 23 24 25 # C-1.14 26 def confirm_multiply(data): 27 for i in data: 28 for j in data: 29 if i != j and i * j % 2: 30 return True 31 return False 32 33 34 # 更优解 35 def has_odd_mut1(data): 36 temp = [] 37 for item in data: 38 if item % 2 and item not in temp: 39 temp.append(item) 40 if len(temp) >= 2: 41 return True 42 else: 43 return False 44 45 46 def has_odd_mut2(data): 47 temp = set() 48 for item in data: 49 if item % 2: 50 temp.add(item) 51 return len(temp) >= 2 52 53 54 l = [2, 4, 6, 7, 9] 55 print(confirm_multiply(l)) 56 57 58 # C-1.15 59 def confirm_different_num(data): 60 for i in range(len(data)): 61 for j in range(len(data)): 62 if i != j and data[i] == data[j]: 63 return False 64 return True 65 66 67 # 更优解 68 def is_diff1(data): 69 temp = set() 70 for item in data: 71 if item not in temp: 72 temp.add(item) 73 else: 74 return False 75 return True 76 77 78 def is_diff2(data): 79 return len(set(data)) == len(data) 80 81 82 l15 = [1, 2, 3, 4, 6, 3] 83 print(confirm_different_num(l15)) 84 85 86 # C-1.16 87 通过更改可变序列索引值进行更改 88 89 90 # C-1.17 91 # 不行,不可变类型不可变 92 def scale(data, factor): 93 for val in data: 94 val *= factor 95 return data 96 97 98 l17 = list(range(9)) 99 print(l17) 100 print(scale(l17, 3)) 101 102 103 # C-1.18 104 l18 = [i*(i+1) for i in range(10)] 105 print(l18) 106 107 108 # C-1.19 109 print(chr(97)) # ‘a‘ 110 l19 = [chr(i) for i in range(97, 123)] 111 112 # 更优解 113 l19 = [chr(ord(‘a‘) + x) for x in range(26)] 114 print(l19) 115 116 117 # C-1.20 118 l20 = [1, 3, 6, 8, 9] 119 shuffle(l20) 120 print(l20) 121 122 123 def my_shuffle(data): 124 new_data = [] 125 data_copy = data.copy() 126 while data_copy: 127 i = randint(0, len(data_copy)-1) 128 new_data.append(data_copy[i]) 129 data_copy.pop(i) 130 return new_data 131 132 133 print(my_shuffle(l20)) 134 print(l20) 135 136 137 # C-1.21 138 content_list = [] 139 try: 140 while True: 141 content = input(‘请输入:‘) 142 content_list.append(content) 143 except EOFError: 144 while content_list: 145 print(content_list.pop()) 146 147 148 # C-1.22 149 def point_multiply(a, b): 150 c = [] 151 for i in range(len(a)): 152 c.append(a[i]*b[i]) 153 return c 154 155 156 a_l = [1, 2, 3] 157 b_l = [4, 5, 6] 158 print(point_multiply(a_l, b_l)) 159 160 161 # C-1.23 162 def confirm_index(data, index): 163 try: 164 return data[index] 165 except IndexError: 166 print("Don‘t try buffer overflow attacks in Python") 167 168 169 l23 = [1, 2, 5] 170 confirm_index(l23, 6) 171 172 173 # C-1.24 174 def sum_vowel_words(data): 175 sum_num = 0 176 for item in data: 177 if item in [‘a‘, ‘e‘, ‘i‘, ‘o‘, ‘u‘, ‘A‘, ‘E‘, ‘I‘, ‘O‘, ‘U‘]: 178 sum_num += 1 179 return sum_num 180 181 182 print(sum_vowel_words(‘abcdefgo‘)) 183 184 185 # C-1.25 186 def replace_punctuation(data): 187 new_data = ‘‘ 188 for item in data: 189 if item in [‘,‘, "‘", ‘.‘, ‘!‘]: 190 item = ‘‘ 191 new_data += item 192 return new_data 193 194 195 # 更优解 196 def replace_punctuation(data): 197 return re.sub("[‘.,]", ‘‘, data) 198 199 200 print(replace_punctuation("Let‘s try, Mike.")) 201 202 203 # C-1.26 204 def test_calculation(): 205 a = int(input(‘a:‘)) 206 b = int(input(‘b:‘)) 207 c = int(input(‘c:‘)) 208 return a + b == c or a == b - c or a * b == c 209 210 211 print(test_calculation()) 212 213 214 # C-1.27 215 def factors(n): 216 k = 1 217 l = [] 218 while k * k < n: 219 if n % k == 0: 220 l.append(k) 221 l.append(n // k) 222 k += 1 223 if k * k == n: 224 l.append(k) 225 return sorted(l) 226 227 228 # 更优解 229 def factors(n): 230 k = 1 231 temp = [] 232 while k * k < n: 233 if n % k == 0: 234 yield k 235 temp.append(n // k) 236 k += 1 237 if k * k == n: 238 yield k 239 for item in temp[::-1]: 240 yield item 241 242 243 print(list(factors(100))) 244 245 246 # C-1.28 247 def norm(v: list, p: int): 248 sum_num = 0 249 for num in v: 250 sum_num += num ** p 251 return sum_num ** (1/p) 252 253 254 print(norm([3, 4], 2))
项目
P-1.29 编写一个 Python 程序,输出由字母 ‘c’,‘a’,‘t’,‘d’,‘o’,‘g’ 组成的所有可能的字符串(每个字母只使用1次)。
P-1.30 编写一个 Python 程序,输入一个大于 2 的正整数,求将该数反复被 2 整除直到商小于 2 为止的次数。
P-1.31 编写一个可以“找零钱”的 Python 程序。程序应该将两个数字作为输入,一个是需要支付的钱数,另一个是你给的钱数。当你需要支付的和所给的钱数不同时,它应该返回所找的纸币和硬币的数量。纸币和硬币的值可以基于之前或现在政府的货币体系。试设计程序,以便返回尽可能少的纸币和硬币。
P-1.32 编写一个 Python 程序来模拟一个简单的计算器,使用控制台作为输入和输出的专用设备。也就是说,计算器的每一次输入做一个单独的行,它可以输入一个数字(如1034或12.34)或操作符(如 + 或 = )。每一次输入后,应该输出计算器显示的结果并将其输出到 Python 控制台。
P-1.33 编写一个 Python 程序来模拟一个手持计算器,程序应该可以处理来自 Python 控制台(表示 Push 按钮)的输入,每个操作执行完毕后内容输出到屏幕。计算器至少应该能够处理基本的算术运算和复位/清除操作。
P-1.34 一种惩罚学生的常见方法是让他们将一个句子重复写很多次。编写独立的 Python 程序,将以下句子 “I will never spam my friends again.” 写 100 次。程序应该对句子进行计数,另外,应该有 8 次不同的随机输入错误。
P-1.35 生日悖论是说,当房间中人数 n 超过 23 时,那么该房间里有两个人生日相同的可能性是一半以上。这其实不是一个悖论,但许多人觉得不可思议。设计一个 Python 程序,可以通过一系列随机生成的生日的实验来测试这个悖论,例如可以 n = 5, 10, 15, 20, …, 100 测试这个悖论。
P-1.36 编写一个 Python程序,输入一个由空格分隔的单词列表,并输出列表中的每个单词出现的次数。在这一点上,你不需要担心效率,因为这个问题会在本书后面的部分予以解决。
1 # P-1.29 编写一个 Python 程序,输出由字母 ‘c’,‘a’,‘t’,‘d’,‘o’,‘g’ 组成的所有可能的字符串(每个字母只使用1次)。 2 3 # 本人做题思路:因为原来不知道python排列函数permutations,故自己算出6个字母有6!=720中排列方式,采用shuffle函数加上集合去重的方法. 4 from random import shuffle 5 6 7 words = [‘c‘, ‘a‘, ‘t‘, ‘d‘, ‘o‘, ‘g‘] 8 new_words_set = set() 9 while len(new_words_set) < 720: 10 new_words = shuffle(words) 11 word = ‘‘.join(words) 12 new_words_set.add(word) 13 # print(new_words_set) 14 15 16 # 更优解 17 from itertools import permutations 18 19 20 def function29(): 21 words_list = [‘c‘, ‘a‘, ‘t‘, ‘d‘, ‘o‘, ‘g‘] 22 new_word = list(map(‘‘.join, permutations(words_list))) 23 return new_word 24 25 26 # print(function29()) 27 # print(len(function29())) 28 29 30 # 用Python实现排列和组合 31 def combinations(iterable, r): # iterable=[1, 2, 3, 4] r = 2 32 pool = tuple(iterable) # pool = (1, 2, 3, 4) 33 n = len(iterable) # n = 4 34 if r > n: 35 return 36 indices = list(range(r)) # indices = [0, 1] 37 yield tuple(pool[i] for i in indices) # yield (1, 2) 38 while True: 39 for i in reversed(range(r)): # for i in [1, 0] 40 if indices[i] != i + n - r: 41 break 42 else: 43 return 44 indices[i] += 1 # indices = 1[0, 2] 2[0, 3] #3[1, 3] 5[1, 3] #6[2, 3] 45 print(‘indice[i]‘, indices) 46 for j in range(i + 1, r): 47 indices[j] = indices[j - 1] + 1 # indices = 4[1, 2] 7[2, 3] 48 print(‘indices[j]‘, indices) 49 yield tuple(pool[i] for i in indices) # yield(1, 3) (1, 4) (2, 3) (2, 4) (3, 4) 50 51 52 # print(list(combinations([1, 2, 3, 4], r=2))) 53 54 55 def permutations(iterable, r=None): 56 pool = tuple(iterable) 57 n = len(iterable) 58 r = n if r is None else r 59 if r > n: 60 return 61 indices = list(range(n)) 62 cycles = list(range(n, n - r, -1)) 63 yield tuple(pool[i] for i in indices[:r]) 64 while n: 65 for i in reversed(range(r)): 66 cycles[i] -= 1 67 if cycles[i] == 0: 68 indices[i:] = indices[i + 1:] + indices[i:i + 1] 69 cycles[i] = n - i 70 else: 71 j = cycles[i] 72 indices[i], indices[-j] = indices[-j], indices[i] 73 yield tuple(pool[i] for i in indices[:r]) 74 break 75 else: 76 return 77 78 # print(list(permutations([1, 2, 3]))) 79 80 81 # P-1.30 82 def divide_two_times(): 83 84 quotient = int(input(‘请输入一个数字: ‘)) 85 times = 0 86 while quotient > 2: 87 quotient = quotient / 2 88 times += 1 89 return times 90 91 92 # divide_two_times() 93 94 95 # P-1.31 96 def change_function(price, payment): 97 currency = [100, 50, 20, 10, 5, 1, 0.5, 0.1] 98 change_list = [] 99 change_amount = payment - price 100 indices = list(range(len(currency))) 101 while change_amount >= 0.1: 102 for i in indices[1:]: 103 if currency[i] <= change_amount < currency[i-1]: 104 change_list.append(currency[i]) 105 change_amount -= currency[i] 106 return change_list 107 108 109 # print(change_function(10.82, 100)) 110 # print(1-0.8) 111 112 113 # P-1.32 114 s = ‘‘ 115 while True: 116 input_num = input(‘请输入:‘) 117 if input_num != ‘=‘: 118 s += input_num 119 else: 120 print(eval(s)) 121 s = ‘‘ 122 123 124 # 参考解法 125 def function32(): 126 temp = input(‘Please input Number1 Operation Numbers2: ‘).split(" ") 127 num1 = int(temp[0]) 128 num2 = int(temp[2]) 129 oper = str(temp[1]) 130 131 if oper == ‘+‘: 132 result = num1 + num2 133 elif oper == ‘-‘: 134 result = num1 - num2 135 elif oper == ‘*‘: 136 result = num1 * num2 137 elif oper == ‘/‘: 138 result = num1 / num2 139 else: 140 raise EOFError(‘Error Input!‘) 141 print(result) 142 143 144 # function32() 145 146 147 # P-1.33 148 s = ‘‘ 149 while True: 150 input_num = input(‘请输入:‘) 151 if input_num != ‘=‘: 152 s += input_num 153 else: 154 print(eval(s)) 155 s = ‘‘ 156 157 158 # P-1.34 159 num = 0 160 while num < 100: 161 input_data = input(‘已抄写%s遍请输入:‘ % num) 162 if input_data == ‘I will never spam my friends again.‘: 163 num += 1 164 print(‘恭喜抄完!!!‘) 165 166 167 # P-1.35 168 # 此方法是直观的观测生日有相同的概率,不能做定量计算 169 from random import randint 170 171 172 def test_birthday(n): 173 birthday_list = [] 174 while len(birthday_list) < n: 175 birthday = randint(1, 365) 176 birthday_list.append(birthday) 177 if len(set(birthday_list)) < len(birthday_list): 178 print(True) 179 return birthday_list 180 181 182 # print(test_birthday(23)) 183 184 185 # 参考解法 186 def function35(num): 187 import math 188 from decimal import Decimal 189 prop = 1 - Decimal((math.factorial(365)))/Decimal((math.pow(365, num) * math.factorial(364 - num))) 190 return prop 191 192 193 def function352(num): 194 import math 195 prop = 1 - math.pow((364/365), (num*(num-1)/2)) 196 return prop 197 198 199 print(function352(23)) # 0.5004771540365807 200 201 202 # P-1.36 203 def words_statistic(data: list): 204 words_dict = {} 205 for words in data: 206 if words not in words_dict: 207 words_dict[words] = 1 208 else: 209 words_dict[words] += 1 210 return words_dict 211 212 213 # print(words_statistic([‘hello‘, ‘hi‘, ‘world‘, ‘hi‘, ‘world‘, ‘hi‘])) 214 # 更优解 215 def function36(): 216 temp = input(‘请输入英语单词: ‘).split(‘ ‘) 217 keys = list(set(temp)) 218 result = dict(zip(keys, [0]*len(keys))) 219 for item in temp: 220 result[item] += 1 221 return result 222 223 224 function36()
以上是关于数据结构与算法 Python语言实现 第一章练习的主要内容,如果未能解决你的问题,请参考以下文章