Python数据结构与算法—递归(金额查错问题)`

Python算法(金额查错问题(递归))`

第一章 Python 算法应用——金额查错



前言

Python 算法广泛应用于我们日常生活,算法是大脑与电脑的交流,学习算法就是学会通过电脑延伸自己的大脑。 程序=算法+数据结构

—`

一、本章涉及知识点

1.循环分行输入与输出
2.排序
3.列表的嵌套
4.列表与字符串的转化
5.字符串间的空格
6.双循环与条件语句的嵌套
7.itertools库

二、算法分析

1.题目分析

题目描述
某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某 1 笔或几笔。如果已知明细账目清单,能通过编程找到漏掉的是哪 1 笔或几笔吗?

如果有多种可能,则输出所有可能的情况。

输入描述
用户输入的第一行是:有错的总金额。

接下来是一个整数 nn,表示下面将要输入的明细账目的条数。

再接下来是 nn 行整数,分别表示每笔账目的金额。

为了方便,不妨假设所有的金额都是整数;每笔金额不超过 1000,金额的明细条数不超过 100。

输出描述
所有可能漏掉的金额组合。每个情况 1 行。金额按照从小到大排列,中间用空格分开。

输入输出样例
示例:
输入

6
5
3
2
4
3
1

输出

1 2 4
1 3 3
3 4

运行限制
最大运行时间:1s
最大运行内存: 256M

解释一下题目
按例子来讲,6是总数,5是接下来的行数,剩下的是每一笔单的金额
输出的 1、2、4 是每笔金额中除去(也就是题目说的漏的)的部分,除去1、2、4剩下3、3相加=6
除去1、3、3 剩下 2+4=6
除去3、4 剩下1+2+3=6

2.代码转换

import math  #引入数学库
import itertools  #引入itertools库
tm = int(input("总金额: "))
n = int(input("分录条数: "))
l1 = [] 
l2 = []
ftm = 0
for i in range(n):  #分行输入金额
    m = int(input("分录金额: "))
    ftm += m  #计算总错误金额
    l1.append(m)  #把每个错误金额都放到一个列表中
l1.sort() #把错误金额从小到大进行排序,如果是从大到小可以使用li.sort(reverse = Ture)
for fn in range(1, n):    #双for嵌套,先考虑错的条目有几个
    for fm in itertools.permutations(l1, fn):   #在确定错误条目数量的基础上,判断具体是哪几个条目。permutations的作用是选定条目。
        if sum(fm) == abs(ftm - tm):            #permutations(l1, fn) 指在l1中选定数量为fn个元素。
                                                 # 把选定的错误条目求和,看是否等于总错误金额与总正确金额差值。abs()为绝对值
            fm = list(fm)                    #将每种错误情况的元素形成一个子列表
            fm.sort()                         #从小到大排序
            if fm not in l2:                #将所有子列表放在一个列表中形成总列表
                l2.append(fm)
            l2.sort()                       #子列表从小到大排序

for h in l2:                                 #从总列表中一个一个拿出子列表,并输出
    print(*h, sep = " ")                    #用*将列表转化为字符串,用sep控制字符串之间的距离

3.重要Python第三方库的讲解

本章选定的重要库为itertools。接下来我将给大家详细讲解itertools库。
1.引入itertools库

import itertools
import itertools as it
from itertools import permutation,product

2.内置工具
2.1 count(start=0,step=1)
创建一个能生成均匀分布序列(等差数列)的迭代器,start指定起点,step指定步长。
注意:count()生成的是无限循环迭代器,用于循环时需要用另外条件终止循环。

import itertools as it
k = 0
for item in it.count(10.7,1.1): #从10.7开始,每次走1.1步
    k+=1
    if k==10: break
    print("k={0},item={1}".format(k,item)) #{}用于浮点数占位

2.2 cycle(iterable)
创建一个迭代器,从一个iterable中循环取出元素并输出。

import itertools as it
k = 0
for item in it.cycle("ABCDE"): #循环取出元素
    print("k=%s,item=%s" % (k, item)) #字符串占位使用%s
    k+=1
    if k ==10: break

2.3 repeat(object, times)
创建迭代器,重复输出object.若未指定times,就无限输出,若指定,输出times次。

import itertools as it
for item in it.repeat("Hello world!", 5):
    print(item)

一个典型用法是给map或zip提供常数值

import itertools as it
print(list(map(pow,range(10),it.repeat(5))))  #输出从1—10的五次方

2.4 accumulate([func,*,initial=None])
可很方便的计算累加列表。
输入

import itertools as it
print(list(it.accumulate([1,2,3,4,5])))  #输出从1-5的每一次累加列表

输出

Hi, PyCharm
[1, 3, 6, 10, 15]

Process finished with exit code 0

输入

import itertools as it
print(list(it.accumulate([1,2,3,4,5],initial=10)))  #从10开始,输出从1-5以10为起点的每一次累加列表

输出

Hi, PyCharm
[10, 11, 13, 16, 20, 25]

2.5 chain(*iterables)
创建一个迭代器,接收多个iterators参数,将它们串接起来。
输入

import itertools as it
print(list(it.chain("ABCD","EFG",'HIJ')))

输出

Hi, PyCharm
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']

Process finished with exit code 0

2.6 compress(data, selectors)
根据selectors所列的各元素对原数据进行过滤处理,挑选出对应的selectors元素为True的data元素。selectors与data的元素是一一对应的。

import itertools as it
print(list(it.compress("ABCDEFG", [0,0,1,0,0,1,1])))

Hi, PyCharm
['C', 'F', 'G']

Process finished with exit code 0

2.7 islice()
以slicing的方式从可迭代对象(iterable)中取出,islice()可理解为升级版range()升级版。
输入

import itertools as it
A = [k for k in range(10)]
for item in it.islice(A, 3):  #将A中元素循环,3为终止
    print(item)

输出

Hi, PyCharm
0
1
2

Process finished with exit code 0

输入

import itertools as it
A = [k for k in range(10)]
for item in it.islice(A, 2, 8, 2): #将A中元素循环,2开始,8结束,2步长
    print(item)

输出

Hi, PyCharm
2
4
6

Process finished with exit code 0

2.8 zip_longest(*iterables,fillvalue=None)
数据搭配迭代

import itertools as it
fruits = ["apple","banana","melon","strawberry"]
prices = [10,20,30]
print(list(it.zip_longest(fruits, prices)))  #双列表搭配
Hi, PyCharm
[('apple', 10), ('banana', 20), ('melon', 30), ('strawberry', None)]

Process finished with exit code 0

2.9 permytations(iterable,r=None)
返回p中任意取r个元素做排列的元组的迭代器。

import itertools as it
fruits = ["apple","banana","melon","strawberry"] 
for i in range(4):
    for item in it.permutations(fruits,i): #每次从列表fruits中取i个元素
        print(*item)

输出

Hi, PyCharm

apple
banana
melon
strawberry
apple banana
apple melon
apple strawberry
banana apple
banana melon
banana strawberry
melon apple
melon banana
melon strawberry
strawberry apple
strawberry banana
strawberry melon
apple banana melon
apple banana strawberry
apple melon banana
apple melon strawberry
apple strawberry banana
apple strawberry melon
banana apple melon
banana apple strawberry
banana melon apple
banana melon strawberry
banana strawberry apple
banana strawberry melon
melon apple banana
melon apple strawberry
melon banana apple
melon banana strawberry
melon strawberry apple
melon strawberry banana
strawberry apple banana
strawberry apple melon
strawberry banana apple
strawberry banana melon
strawberry melon apple
strawberry melon banana

Process finished with exit code 0

总结

以上就是将Python递归思想应用于金额查错问题。以及itertools库的常用内置函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值