数据结构与算法 Python语言实现 第四章练习
Posted xiaomingyang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法 Python语言实现 第四章练习相关的知识,希望对你有一定的参考价值。
巩固
1 # R-4.1 2 def find_max(data): 3 n = len(data) 4 if n == 1: 5 return data[0] 6 elif data[0] > data[1]: 7 data.pop(1) 8 elif data[0] < data[1]: 9 data.pop(0) 10 return find_max(data) 11 12 13 # print(find_max([1, 2, 3, 4, 6, 5])) 14 # 时间:O(n) 空间:O(n) 15 16 17 # R-4.2 18 def power(x, n): 19 if n == 0: 20 return 1 21 else: 22 return x * power(x, n-1) 23 24 25 # print(power(2, 5)) 26 27 28 # R-4.3 29 def power(x, n): 30 if n == 0: 31 return 1 32 else: 33 partial = power(x, n // 2) 34 result = partial * partial 35 if n % 2 == 1: 36 result *= x 37 return result 38 39 40 # print(power(2, 18)) 41 42 43 # R-4.4 44 def reverse(S, start, stop): 45 if start < stop - 1: 46 S[start], S[stop-1] = S[stop-1], S[start] 47 reverse(S, start+1, stop-1) 48 49 50 S = [4, 3, 6, 2, 6] 51 reverse(S, 0, 5) 52 # print(S) 53 54 55 # R-4.5 56 # def puzzle_solve(k, S, U): 57 # for i in sorted(U): 58 # S.append(i) 59 # U.remove(i) 60 # if k == 1: 61 # print(S) 62 # else: 63 # puzzle_solve(k-1, S, U) 64 # S.remove(i) 65 # U.append(i) 66 # 67 # 68 # puzzle_solve(3, [], [‘a‘, ‘b‘, ‘c‘, ‘d‘]) 69 70 71 # --------------R4-5------------------------ 72 # Note that S is our attempt at solving the sequence and U is our set of all possible numbers that are unused 73 def solves(S): 74 # Note, this is a random solution to the pseudoproblem 75 return S == [‘d‘, ‘b‘, ‘c‘] 76 77 78 def PuzzleSolver(k, S, U): 79 for e in sorted(U).copy(): 80 S.append(e) 81 U.remove(e) 82 if k == 1: 83 print(S) 84 if solves(S): 85 print( f‘Solution found: {S}‘) 86 else: 87 PuzzleSolver(k-1, S, U) 88 U.add(S.pop()) #removes the last item of an array 89 90 # PuzzleSolver(3, [], {‘a‘,‘b‘,‘c‘,‘d‘}) 91 92 93 # R-4.6 94 def sum_harmonic(n): 95 if n == 1: 96 return 1 97 else: 98 return sum_harmonic(n-1) + 1/n 99 100 # print(sum_harmonic(4)) 101 102 103 # R-4.7 104 def transform_to_num(S): 105 num_list = [‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘] 106 # s = list(S) 107 # for i in s: 108 # if i not in num_list: 109 # s.remove(i) 110 # return int(‘‘.join(s)) 111 112 113 # ----------R4-7--------------------- 114 """ 115 Note, we can solve this by knowing that a number can be decomposed into: 116 a*1e0 + a2*1e1 + a3*1e2, etc... 117 118 So 123 is 119 1*1 + 2*10 + 3*100 120 121 """ 122 123 124 def str_2_int(string, index=0): 125 length = len(string) 126 if index == length - 1: 127 return int(string[index]) 128 else: 129 return int(string[index]) * 10 ** (length - index - 1) + str_2_int(string, index + 1) 130 131 132 """ 133 This runs in 0(n) time and space 134 135 """ 136 137 # ans = str_2_int(‘12342543‘) 138 # print(ans, type(ans)) 139 140 141 # R-4.8 142 import math 143 144 145 def isabel_method(data): 146 n = len(data) 147 try: 148 assert math.log(n, 2) % 1 == 0 149 except AssertionError: 150 return ‘数据需要为2的幂‘ 151 if n == 1: 152 return data[0] 153 else: 154 B = [None] * (n // 2) 155 for i in range(len(B)): 156 B[i] = data[2*i] + data[2*i + 1] 157 return isabel_method(B) 158 159 160 # print(isabel_method([1, 2, 3, 4, 5, 6, 7, 8])) 161 162 163 # ---------------R4-8--------------------- 164 import math 165 166 167 # def isabel_method(A): 168 # assert math.log(len(A), 2) % 1 == 0, ‘Your array must be a length that is a power of 2‘ 169 # if len(A) == 1: 170 # return A[0] 171 # else: 172 # B = [None] * (len(A) // 2) 173 # for i in range(len(B)): 174 # B[i] = A[2 * i] + A[2 * i - 1] 175 # return isabel_method(B) 176 177 178 """ 179 The recursion will be called log(n) times, since the array is divided in half each time 180 181 182 Each call will require you to access all of the remaining elements, which means it will be 183 n + n/2 + n/4 + ... 184 185 This is equal to n* Sum(1/2**i), which is <2n 186 187 Therefore, the running time is O(n), although a much slower implementation than just adding them up element by element 188 189 """ 190 191 # print(isabel_method([1, 2, 3, 4, 5, 6, 7, 8])) 192 # try: 193 # print(isabel_method([1, 2, 3, 4, 5, 6, 7])) 194 # except Exception as e: 195 # print(e)
创新
1 # C-4.9 2 import os 3 4 5 def find_max_min_num(S, index=0): 6 if index == len(S) - 1: 7 return S[index], S[index] 8 else: 9 max_value, min_value = find_max_min_num(S, index+1) 10 return max(S[index], max_value), min(S[index], min_value) 11 12 # 13 # test_S = [1, 2, 3, 5, 4, 7, 3] 14 # max_val = find_max_min_num(test_S) 15 # print(max_val) 16 17 18 # C-4.10 19 def find_log_int(num): 20 if num // 2 < 1: 21 return 0 22 if num // 2 >= 1: 23 return 1 + find_log_int(num // 2) 24 25 26 # print(find_log_int(7)) 27 28 29 # C-4.11 30 def confirm_unique(data): 31 if len(data) == 1: 32 return True 33 else: 34 if data[0] in data[1:]: 35 return False 36 else: 37 return confirm_unique(data[1:]) 38 39 40 # print(confirm_unique([1, 2, 3, 4, 5, 6, 3])) 41 42 43 # C-4.12 44 def calculate_multiplication(m, n): 45 if m == 1: 46 return n 47 else: 48 return n + calculate_multiplication(m-1, n) 49 50 51 # print(calculate_multiplication(3, 5)) 52 53 54 # C-4.14 55 def han_nuo_ta(n): 56 if n == 1: 57 return 1 58 else: 59 return han_nuo_ta(n-1) + 1 + han_nuo_ta(n-1) 60 61 62 # print(han_nuo_ta(5)) 63 64 65 # ---------C4-14----------------------- 66 import time 67 from IPython.display import clear_output 68 69 70 class TowerOfHanoi(): 71 def __init__(self, n=4): 72 self._n = n 73 self._array = [[], [], list(reversed(range(n)))] 74 self._lengths = [0, 0, n] 75 76 def draw_towers(self): 77 rows = [] 78 rows.append([‘ 1 ‘, ‘ 2 ‘, ‘ 3 ‘]) 79 rows.append([‘ _____ ‘, ‘ _____ ‘, ‘ _____ ‘]) 80 for i in range(max(self._lengths)): 81 row = [] 82 for j in range(3): 83 if i < self._lengths[j]: 84 row.append(‘ ‘ + str(self._array[j][i]) + ‘ ‘) 85 else: 86 row.append(‘ ‘) 87 rows.append(row) 88 89 for r in reversed(rows): 90 print(‘‘.join(r)) 91 92 def __getitem__(self, index): 93 return self._array[index] 94 95 def pop(self, index): 96 self._lengths[index] -= 1 97 return self[index].pop() 98 99 def getlen(self): 100 return self._lengths 101 102 def __setitem__(self, index, value): 103 if self[index] and self[index][-1] < value: 104 raise ValueError(f‘Illegal move. Cannot place block with size {value} on block {self[index][-1]}‘) 105 else: 106 self[index].append(value) 107 self._lengths[index] += 1 108 109 def _move_stack(self, n_disks, start_peg, help_peg, target_peg): 110 time.sleep(0.5) 111 clear_output() 112 self.draw_towers() 113 114 if n_disks == 1: 115 self._count += 1 116 value = self.pop(start_peg) 117 try: 118 self[target_peg] = value 119 except Exception as e: 120 print(e) 121 self[start_peg] 122 123 else: 124 # Move the upper stack to the helper peg 125 self._move_stack(n_disks - 1, start_peg, target_peg, help_peg) 126 # Move the lowest item to the target peg 127 self._move_stack(1, start_peg, help_peg, target_peg) 128 # Move the upper stack to the target peg 129 self._move_stack(n_disks - 1, help_peg, start_peg, target_peg) 130 131 def solve_hanoi(self): 132 self._count = 0 133 self._move_stack(self.getlen()[2], 2, 1, 0) 134 135 time.sleep(0.5) 136 clear_output() 137 self.draw_towers() 138 139 print(f‘ This took a total of {self._count} moves!‘) 140 141 142 # t = TowerOfHanoi(5) 143 # t.solve_hanoi() 144 145 # ---------------C4-15----------------------------- 146 """ 147 Here, we want combinations, not permutations 148 149 150 We rely on the addition of an empty set value ‘UNK‘ 151 152 For each stage of the recursion, we add one more value from the sequence 153 and for each current item either add another UNK or that value 154 155 The final layer of that tree will contain exactly one copy of each unique set 156 157 """ 158 UNK = chr(1000) 159 160 161 def sub_rec(U, S): 162 """ 163 U is the current set 164 S is the remaining sequence 165 """ 166 if len(S) == 0: 167 print(‘{‘, str([x for x in U if x != UNK])[1:-1], ‘}‘) 168 169 else: 170 val = S.pop() 171 U.append(UNK) 172 sub_rec(U, S) 173 U.pop() 174 175 U.append(val) 176 sub_rec(U, S) 177 U.pop() 178 S.append(val) 179 180 181 def print_subsets(U): 182 sub_rec([], list(U)) 183 184 185 # print_subsets({1, 2, 3, 4, 5}) 186 187 188 # C-4.16 189 def reverse_str(word, index=0): 190 if index == len(word) - 1: 191 return [word[index]] 192 else: 193 ans = reverse_str(word, index+1) 194 ans.append(word[index]) 195 if index == 0: 196 ans = ‘‘.join(ans) 197 return ans 198 199 200 # print(reverse_str(‘abc‘)) 201 202 203 # C-4.17 204 def confirm_hui_str(word): 205 if len(word) == 1: 206 return True 207 else: 208 if word[0] != word[len(word)-1]: 209 return False 210 return confirm_hui_str(word[1:-1]) 211 212 213 # print(confirm_hui_str(‘abacaba‘)) 214 215 216 # C-4.18 217 def confirm_vowel(word): 218 vowel_list = [‘a‘, ‘e‘, ‘i‘, ‘o‘, ‘u‘] 219 if len(word) == 1: 220 if word[0] in vowel_list: 221 return 1 222 else: 223 return -1 224 elif word[0] in vowel_list: 225 return 1 + confirm_vowel(word[1:]) 226 else: 227 return -1 + confirm_vowel(word[1:]) 228 229 230 # print(confirm_vowel(‘abcdeae‘)) 231 232 233 # C-4.19(没有独立完成哈哈) 234 # def realign_num(data): 235 # if len(data) == 1: 236 # return data 237 # elif data[0] % 2 == 1: 238 # data.append(data.pop(0)) 239 # return data[:1] + realign_num(data[:-1]) 240 # else: 241 # return data[:1] + realign_num(data[:-1]) 242 # 243 244 # print(realign_num([1, 2, 3, 4])) 245 246 247 # --------------C4-18----------------- 248 """ 249 Approaches: 250 1) Two lists that you join at the end 251 2) Add new even numbers to the front and odd ones to the back 252 253 254 """ 255 256 257 def evenoddbylists(S, index=0): 258 if index == len(S) - 1: 259 if len(S) == 1: 260 return S 261 elif S[index] % 2 == 0: 262 return [S[index]], [] 263 else: 264 return [], [S[index]] 265 else: 266 evens, odds = evenoddbylists(S, index + 1) 267 if S[index] % 2 == 0: 268 evens.append(S[index]) 269 else: 270 odds.append(S[index]) 271 if index == 0: 272 return evens + odds 273 else: 274 return evens, odds 275 276 277 def evenoddbyappending(S, index=0): 278 if index == len(S) - 1: 279 return [S[index]] 280 281 else: 282 if S[index] % 2 == 1: # If odd, we want to add it to the end of the list 283 return evenoddbyappending(S, index + 1) + [S[index]] 284 else: 285 return [S[index]] + evenoddbyappending(S, index + 1) 286 287 288 # sequences = [[1, 2, 3, 4, 5, 6, 7, 8], [4, 3, 65, 23, 5, 46, 765, 3, 45, 23], [1], [2, 2]] 289 # print(‘Two lists approach‘) 290 # for s in sequences: 291 # print(evenoddbylists(s)) 292 # 293 # print(‘ Adding each element approach‘) 294 # for s in sequences: 295 # print(evenoddbyappending(s)) 296 297 """ 298 Final notes: the second approach is not desirable with lists because it is O(n) due to the fact that 299 appending an entire list of length m to another requires O(m) time. This could be solved with Linked Lists when 300 we get to that part of the book 301 302 303 Note also that both answers are correct, but the numbers are in a different order 304 """ 305 306 307 # C-4.20 308 # def sort_by_k(S, k, index=0): 309 # if index == len(S) - 1: 310 # return [S[index]] 311 # else: 312 # if S[index] <= k: 313 # return [S[index]] + sort_by_k(S, k, index+1) 314 # else: 315 # return sort_by_k(S, k, index+1) + [S[index]] 316 317 318 # test_s = [1, 6, 5, 2, 3, 5, 7, 9, 11] 319 # print(sort_by_k(test_s, 5.5)) 320 321 def add_lists(a, b): 322 if a and b: 323 return a + b 324 else: 325 return b or a 326 327 328 def split_by_k(S, k, index=0): 329 if len(S) == 1: 330 return S 331 elif index == len(S) - 1: 332 if S[index] < k: 333 return [S[index]], [], [] 334 elif S[index] > k: 335 return [], [], [S[index]] 336 else: 337 return [], [S[index]], [] 338 else: 339 low, mid, high = split_by_k(S, k, index+1) 340 if S[index] < k: 341 low = add_lists(low, [S[index]]) 342 elif S[index] > k: 343 high = add_lists(high, [S[index]]) 344 else: 345 mid = add_lists(mid, [S[index]]) 346 if index == 0: 347 return low + mid + high 348 else: 349 return low, mid, high 350 351 352 S_test = [1, 2, 3, 5, 6, 7, 8, 10, 12] 353 # print(split_by_k(S_test, 6)) 354 355 356 # C-4.21 357 def find_sum(S, k, index1=0, index2=1): 358 if S[index1] + S[index2] == k: 359 return S[index1], S[index2] 360 elif index2 == len(S) - 1: 361 index1 += 1 362 index2 = index1 + 1 363 return find_sum(S, k, index1, index2) 364 else: 365 return find_sum(S, k, index1, index2+1) 366 367 368 # S_test = [1, 2, 3, 5, 6, 7, 8, 10, 12] 369 # print(find_sum(S_test, 22)) 370 371 372 # ----------------C4-21---------------------- 373 """ 374 Note: there is a brute force approach, but we will use the one with dictionaries instead 375 376 377 Additional Note: I learned an important thing about using mutable objects as defaults in python 378 Successive calls used the growing key_set, rather than initializing it as set() every time. 379 380 """ 381 382 383 # The following line is the wrong way to do the initialization... 384 # def find_pair(S, target, key_set = set(), index=0): 385 386 def find_pair(S, k, key_set=None, index=0): 387 if key_set is None: 388 key_set = set() 389 key = k - S[index] 390 if len(S) <= 1: 391 return None 392 elif index == len(S) - 1: 393 if key in key_set: 394 return key, S[index] 395 else: 396 return None 397 else: 398 if key in key_set: 399 return key, S[index] 400 else: 401 key_set.add(S[index]) 402 return find_pair(S, k, key_set, index+1) 403 404 405 sequence = [1, 2, 3, 4, 5, 6, 7, 8] 406 407 # for i in range(20): 408 # print(f‘For the value {i}, the resulting pair is {find_pair(sequence, i)}‘) 409 410 411 # C-4.22 412 def power_loop(x, n): 413 factor = n 414 partial = 1 415 416 counter = 0 417 while factor: 418 factor = factor >> 1 419 counter += 1 420 421 while counter + 1: 422 partial *= partial 423 if n >> counter & 1: 424 partial *= x 425 counter -= 1 426 return partial 427 428 429 # combos = [(2, 13), (2, 15), (3, 15), (10, 7), (2, 5)] 430 # for b, p in combos: 431 # print(‘ ‘, power_loop(b, p), b ** p)
项目
1 # P-4.23 2 import os 3 4 5 def find(path, filename): 6 abspath = os.path.join(path, filename) 7 if os.path.isdir(abspath): 8 for sub_filename in os.listdir(abspath): 9 if os.path.isdir(os.path.join(abspath, sub_filename)): 10 find(abspath, sub_filename) 11 else: 12 print(os.path.join(abspath, sub_filename)) 13 14 15 # find("F:", "工作总结") 16 17 18 # P-4.24 19 20 21 # ------------P4-24------------------ 22 """The ones we want to ultimately solve are: 23 pot + pan = bib 24 dog + cat = pig 25 boy+ girl = baby 26 """ 27 28 29 class SummationSolver: 30 def __init__(self, a, b, c): 31 self._a = a 32 self._b = b 33 self._c = c 34 self._max_len = len(c) # c cannot be shorter than a or b under the rules 35 self._count = 0 36 37 def _t2i(self, text, lookup): # text to int 38 total = 0 39 length = len(text) 40 for i in range(length): 41 total += int(lookup[text[i]]) * 10 ** (length - i - 1) 42 43 return total 44 45 def summation_check(self, a, b, c, U): 46 """ 47 a + b = c using the keys, value pairs in U 48 """ 49 if self._t2i(a, U) + self._t2i(b, U) == self._t2i(c, U): 50 self._count += 1 51 print( 52 f‘One solution is: {self._t2i(a, U)} + {self._t2i(b, U)} = {self._t2i(c, U)}. Check:{self._t2i(a, U) + self._t2i(b, U)}‘) 53 print(‘Dictionary is :‘, U) 54 print(‘ ‘) 55 return True 56 else: 57 return False 58 59 def _solver_r(self, a, b, c, S, index, U, nums): 60 if index >= len(S): # Note, this means we are past the final index 61 # print(U) 62 return self.summation_check(a, b, c, U) 63 elif S[index] in U: # If the next letter in the sequence is already in the dictionary, skip it 64 return self._solver_r(a, b, c, S, index + 1, U, nums) 65 else: 66 for number in nums.copy(): 67 U[S[index]] = number 68 nums.remove(number) 69 ans = self._solver_r(a, b, c, S, index + 1, U, nums) 70 nums.add(number) 71 del U[S[index]] 72 73 def solve(self): 74 U = {} 75 nums = set(range(10)) 76 S = list(self._a) + list(self._b) + list(self._c) 77 self._count = 0 78 79 self._solver_r(self._a, self._b, self._c, S, 0, U, nums) 80 81 if self._count == 0: 82 print(‘Sorry, no solution found! :(‘) 83 84 else: 85 print(f‘There are a total of {self._count} solutions‘) 86 87 88 # a = SummationSolver(‘pot‘, ‘pan‘, ‘bib‘) 89 a = SummationSolver(‘boy‘, ‘girl‘, ‘babys‘) 90 # a = SummationSolver(‘boy‘, ‘girl‘, ‘babysda‘) 91 a.solve() 92 93 94 # P-4.25 95 def draw_interval(c): 96 print(c * ‘-‘) 97 for i in range(2**c-1): 98 sum_1 = 1 99 for j in bin(i)[::-1]: 100 if j == ‘1‘: 101 sum_1 += 1 102 else: 103 break 104 print(sum_1 * ‘-‘) 105 print(c * ‘-‘) 106 107 108 # draw_interval(3) 109 110 111 # ------------P4-25------------------- 112 """ 113 The hint is that we should use a loop from 0 to 2**c -2 114 and that the number of ticks should be one more than the number of consecutive 1s. 115 116 That‘s a great hint! 117 118 """ 119 120 121 def english_ruler(n=3, repeats=10): 122 limit = repeats * (2 ** n - 2) 123 counter = 0 124 while counter <= limit: 125 dashes = 1 126 sub_counter = counter 127 while sub_counter & 1: 128 dashes += 1 129 sub_counter = sub_counter >> 1 130 dashes = min(dashes, n) 131 print(‘-‘ * dashes) 132 counter += 1 133 134 135 # english_ruler(4, 3) 136 137 138 # ----------------P4-26----------------------- 139 """ 140 Note, this was solved in C4-14 141 142 """ 143 144 # t = TowerOfHanoi(6) 145 # t.solve_hanoi() 146 147 148 # P-4.27 149 def my_walk(path): 150 dirpath = path 151 dir_path_list = [] 152 sub_path_list = [] 153 if os.path.isdir(path): 154 for filepath in os.listdir(path): 155 if os.path.isdir(os.path.join(path, filepath)): 156 dir_path_list.append(filepath) 157 else: 158 sub_path_list.append(filepath) 159 return dirpath, dir_path_list, sub_path_list 160 161 162 # print(my_walk(‘F:工作总结‘))
以上是关于数据结构与算法 Python语言实现 第四章练习的主要内容,如果未能解决你的问题,请参考以下文章