数据结构与算法:Python语言实现--Python入门 数据结构与算法 Python 语言实现 课后答案

数据结构与算法题目 专栏收录该内容
69 篇文章 8 订阅

说明

'''
这是《数据结构与算法 Python 语言实现》 (古德里奇)版,每一章书后习题和自己的一些解答,、
我已经买了这本书,因为想在看完每一章后,完成习题,所以记录下来!
这篇文章是第一章的习题内容!因为题目太长,懒得自己书写,我拍下了习题,并且直接用截图作为题目!
'''

巩固题

编写一个Python函数 is_multiple(n, m),用来接收两个整数值 n 和 m,
如果 n 是 m 的倍数,即存在整数 i 使得 n = mi,那么函数返回 True,否则返回 False

def is_multiple(n, m):
    return (n % m == 0)

print(is_multiple(4, 2))

不能用乘法、除法、取余的操作来判断传入的数是偶数(返回Ture)

def is_even(k):
    return (k & 1 == 0)


print(is_even(5))
# 用减法?
def is_even(k):
    k = abs(k)
    while k > 1:
        k = k - 2
    return (k == 0)


print(is_even(10))

传入一个序列,找出其中最大和最小的值,并以一个长度为2的元组形式返回,不能使用max和min

def minmax(data):
    small = big = data[0]  # 假设非空
    for val in data:
        if val < small:
            small = val
        if val > big:
            big = val
    return small, big


print(minmax([1, 2, 5, 8, 6])) # 结果:(1,8)

接受一个正整数n,返回1~n的平方和

def sum_of_squares(n):
    total = 0
    for j in range(1, n + 1):
        total += j * j
    return total


print(sum_of_squares(5)) # 55
# 用推导式来写
def sum_of_squares(n):
    return sum(j * j for j in range(1, n + 1))


print(sum_of_squares(5)) # 55

接受一个正整数n,返回1~n中奇数的平方和

def sum_of_squares(n):
    total = 0
    for j in range(1, n + 1, 2): # 隔两个取一个,从1开始数
        total += j * j
    return total


print(sum_of_squares(5))
def sum_of_squares(n):
    return sum(j * j for j in range(1, n + 1, 2))


print(sum_of_squares(5))

在这里插入图片描述

li = [1, 2, 5, 6, 8]
print(len(li))  # 5

print(li[-4])  # 2

print(li[len(li)+(-4)]) # 2

索引规律为:负值+序列长度 即是: k+n

在这里插入图片描述

# 虽然很简单,但是“前开后闭”很容易错
range(50,81,10)

在这里插入图片描述

for i in range(8, -10, -2):
    print(i, end=" ") 

在这里插入图片描述

def get_num(n):
    return [2 ** i for i in range(n)]


print(get_num(9))

在这里插入图片描述

import random

def choice(data):
    return data[random.randrange(len(data))]


print(choice([1, 2, 3, 4])) # 结果是从列表中随机选择一个数

创新题

在这里插入图片描述

def has_odd_pair(data):
    count = 0
    for j in range(len(data)):
        if data[j] % 2 == 1:
            count += 1
            if count == 2:
                return True
    return False


print(has_odd_pair([5, 1, 3, 6]))

# 乘积要是奇数,奇数个数必须至少有两个

在这里插入图片描述

# 让后一个数和前面的数一次进行比较,类似冒泡排序
def distinct(data):
    for k in range(1, len(data)):
        for j in range(k):
            if data[j] == data[k]:
                return False
    return True  


print(distinct([1, 3, 6, 5, 4])) # True
print(distinct([1, 3, 6, 3, 4])) # False

在这里插入图片描述

lis=[i*(i+1) for i in range(0,10)]
print(lis)

在这里插入图片描述

Alphabet = [chr(k) for k in range(97, 123)]

print(Alphabet)
# 法二

Alphabet = list(map((lambda x: chr(ord('a') + x)), range(26)))
print(Alphabet)

在这里插入图片描述

'''
Hint:
Consider randomly swapping an element to the first position, 
then randomly swapping a remaining element to the second position,
and so on.
'''

在这里插入图片描述

# 翻转 reversed 列表才有
lines = []
while True:
    try:
        single = input()
        lines.append(single)
    except EOFError: 
    # 出现“EOFError Python”,就意味着发现了一个不期望的文件尾,而这个文件尾通常是Ctrl-d引起的
        break  
print('\n'.join(reversed(lines)))

'''
fjsd
fasdf
asdfwe
^D # 结束
asdfwe
fasdf
fjsd
d
'''

在这里插入图片描述

return [a[k]*b[k] for k in range(n)]
def get_num(a, b):
    import numpy as np
    return np.array(a) * np.array(b)
    
a = [1, 2, 3]
b = [4, 5, 6]
print(get_num(a ,b))

在这里插入图片描述

def get_erro(data, i):
   try:
       return data[i]
   except IndexError:
       print("Don't try buffer overflow attacks in Python!")

data = [1, 2, 3 ]
get_erro(data, 3)

在这里插入图片描述

def num_vowels(text):
    total = 0
    for ch in text.lower():
        if ch in 'aeiou':
            total += 1
    return total


print(num_vowels("aEcdefjdaeo"))

在这里插入图片描述

# 法一 
string = "Let's try, Mike."
ret = string.split(" ")

for aph in ret:

    res = ""
    for el in aph:
        if ord(el.lower()) in range(97, 123): # 用字母对应的码值来筛选
            res += el
    print(res, end=" ")
# 法二:正则表达式
import re

string = "Let's try, Mike."
res = re.sub("[.',]", "", string)
print(res)

在这里插入图片描述

def get_num():
    li = []
    while True:
        temp = int(input("please enter three num:"))
        li.append(temp)
        if len(li) == 3:
            break
    a, b, c = li[0], li[1], li[2]
    if (a + b == c) or (a == b - c) or (a * b == c):
        return True
    else:
        return False


print(get_num())

在这里插入图片描述

def factors(n):
    k = 1
    temp = []
    while k * k < n:
        if n % k == 0:
            yield k
            temp.append(n // k)
        k += 1
    if k * k == n:
        yield k
    for item in temp[::-1]:
        yield item


res = list(factors(100))
print(res) # [1, 2, 4, 5, 10, 20, 25, 50, 100]

在这里插入图片描述

# 法一
def norm(v, p=2):
    import math
    return math.sqrt(sum(pow(x, p) for x in v))


v = [3, 4]
print(norm(v)) # 5.0
# 法二
def norm(v, p=2):
    temp = sum(val ** p for val in v)
    return temp ** (1 / p)


v = [3, 4]
print(norm(v)) # 5.0

项目

在这里插入图片描述

这道题解法有很多(实质:全排列)

递归思路

# 原书本中做法:递归
def permute(bag, permutation):
    # When the bag is empty, a full permutation exists
    if len(bag) == 0:
        print(''.join(permutation))
    else:
        # For each element left in the bag
        for k in range(len(bag)):
            # Take the element out of the bag and put it at the end of the permutation
            permutation.append(bag.pop(k))
            # Permute the rest of the bag (recursively)
            permute(bag, permutation)
            # Take the element off the permutation and put it back in the bag
            bag.insert(k, permutation.pop())


permute(list('catdog'), [])
'''
原书中用的是递归方法,而且还用了列表的方法,更加简便了
'''
# 详细来解答下思路过程

'''
例如对[1,2,3]进行全排:

固定数组的第一个元素list[0],然后对之后的元素list[1:]进行递归全排列,得到list[1:]的全排列之后,
遍历list[1:]的全排列结果,将list[0]分别插入每一个结果中的每一个位置。
如数组[1,2,3],固定1,对[2,3]全排列,得到结果[2,3]和[3,2]。
将1插入每一个结果的每一个位置,即对于[2,3],将1插入之后得到[1,2,3]、[2,1,3]、[2,3,1];
对于[3,2],将1插入之后得到[1,3,2]、[3,1,2]、[3,2,1]
'''
# 第一种递归做法
def full_permutation(list):
    if list == None: # 递归出口
        return None
    if len(list) == 1:  # 因为是从list[1]处开始递归的,若len(list)<=1,list会越界
        return [list]
    res = []
    left = list[0]
    right = full_permutation(list[1:])
    for i in right:
        for j in range(len(i) + 1):
            res.append(i[:j] + [left] + i[j:])
    return res


print(full_permutation([1, 2, 3]))


# 第二种递归做法
# 摘自:https://blog.csdn.net/ggdhs/article/details/90285794
'''
还是以【1,2,3】为例,
第一步,先把1放在第一位,然后对【2,3】进行全排列,那如何对【2,3】进行全排列呢,
分别固定2、3在第一位,对剩下的元素进行全排列,得到【2】、【3】,因此得到【2,3】,【3,2】,
因此得到【1,2,3】和【1,3,2】。继续,将2固定在第一位,即交换1,2…………

具体来说做法如下:
全排列:
1、列表只有一个元素[a],它的全排列只有a。
2、列表有两个元素[a, b],它的全排列为[a, b], [b, a]:
{ 将第一个元素a固定,对b进行全排列得到[a, b]。
将第一个元素与第二个元素交换得到[b, a]。
将b固定,对a进行全排列,得到[b, a] }
3、列表有三个元素[a, b, c]
{ 将a固定,对bc进行全排列{ 将b固定,对c全排列[abc]。交换bc,将c固定对b进行全排列[acb] }
交换ab,[b, a, c] 对ac进行全排列{ … }
… …}
4、列表有n个元素,将第一个元素固定,对剩下n - 1个元素进行全排列。
将第一个元素依此与其他元素交换,对每次交换后剩下的n-1个元素进行全排列。
5、对剩下的n - 1个元素全排列,同上,固定后对n - 2排列。
6、直到数组数量为1,全排列就是它自己,完成一次排列。

问题是:如何确定当前数组的已经固定了n-1个元素,这时我们可以引入begin和end两个指针。
当begin等于end时,就说明当前数n个元素都已经固定好了,直接返回结果当前数组,就是一次排列。
这也是递归的终止条件
'''
def permutations(arr, begin, end):
    if begin == end:  # 当begin等于end,就说明数组中的元素都全部固定了,这是递归的终止条件
        print(arr)  # 打印当前这一次排列
    else:
        for index in range(begin, end):
            arr[index], arr[begin] = arr[begin], arr[index]
            # 数组的第一个元素和其他任意一个元素元素都交换一次,包括刚开始他自己
            permutations(arr, begin + 1, end)
            # 交换完成之后,对剩下的元素进行交换,即全排
            arr[index], arr[begin] = arr[begin], arr[index]
            # 当以arr[index]在第一位时,都排列完的时候,还要将将交换双方换回来,在进行下一次循环


permutations([1, 2, 3], 0, len([1, 2, 3]))
# 法二
def permute():
    temp = ['c', 'a', 't', 'd', 'o', 'g']
    from itertools import permutations
    ret = list(map(''.join, permutations(temp)))
    print(ret, len(ret)) # 总共有720个


permute()
# 法三 全排列
def perm(s=''):
    if len(s) <= 1:
        return [s]
    sl = []
    for i in range(len(s)):
        for j in perm(s[0:i] + s[i + 1:]):
            sl.append(s[i] + j)
    return sl


def main():
    perm_nums = perm('catdog') # 可能包含重复的串
    no_repeat_nums = list(set(perm_nums)) # 对结果去重
    print('perm_nums', len(perm_nums), perm_nums)
    print('no_repeat_nums', len(no_repeat_nums), no_repeat_nums)


if __name__ == '__main__':
    main()

'''
这个问题还涉及“去重”,会专门开辟一篇文章来写:递归和非递归实现全排列 (去重和不去重)

'''

在这里插入图片描述

def get_num():
    item = int(input("please enter a num:"))
    count = 0
    while item >= 2:
        item //= 2
        count += 1
    return count


print(get_num())

在这里插入图片描述

def back_money():
    coins = {'0.5': 0, '1': 0, '5': 0, '10': 0, '20': 0, '50': 0, '100': 0}
    temp = input("Please input Pay and Total money: \n").split(" ")
    pay, total = int(temp[0]), int(temp[1])
    rest = total - pay

    coins[100] = int(rest / 100)
    rest = int(rest % 100)
    coins[50] = int(rest / 50)
    rest = int(rest % 50)
    coins[20] = int(rest / 20)
    rest = int(rest % 20)
    coins[10] = int(rest / 10)
    rest = int(rest % 10)
    coins[5] = int(rest / 5)
    rest = int(rest % 5)
    coins[1] = int(rest / 1)
    rest = int(rest % 1)
    coins[0.5] = int(rest / 0.5)
    rest = int(rest % 0.5)

    return coins.values()


print(back_money)
'''
Please input Pay and Total money: 
22 100
dict_values([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 3, 0])
'''

在这里插入图片描述

def easy_abacus():
    temp = input("Please input Number1 Operation Number2: \n").split(" ")
    num1 = int(temp[0])
    num2 = int(temp[2])
    oper = str(temp[1])
    if oper == '+':
        result = num1 + num2
    elif oper == '-':
        result = num1 - num2
    elif oper == '*':
        result = num1 * num2
    elif oper == '/':
        result = num1 / num2
    else:
        raise EOFError("Error Input!")
    return result


print(easy_abacus())

'''
Please input Number1 Operation Number2: 
6 * 5
30
'''

在这里插入图片描述
在这里插入图片描述

# 解法来自:https://blog.csdn.net/Harrytsz/article/details/86645857

def birth_age(num):
    import math
    prop = 1 - math.pow((364 / 365), (num * (num - 1) / 2))
    return prop


print(birth_age(23))

在这里插入图片描述

def worlds_num():
    import string
    temp = input("Please input a string: \n").strip(string.punctuation).split(" ")
    keys = list(set(temp))
    result = dict(zip(keys, [0] * len(keys)))
    for item in temp:
        result[item] += 1
    return result


print(worlds_num())

# 用字符串提供的方法来完成
def worlds_num():
    temp = input("Please input a string: \n").split(" ")
    wait=list(set(temp))
    for words in wait:
        print("%s:%d"%(words,temp.count(words)),end=" ")


worlds_num()
'''
Please input a string: 
i love you you love me
you:2 love:2 i:1 me:1 

'''
  • 13
    点赞
  • 4
    评论
  • 99
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值