看完教程里的内容,你应该已经了解基本语法、运算、控制流、输入输出、常用数据结构,以及函数、类、模块等程序复用概念。接着就可以开始训练,从基本的开始,把上述知识融会贯通。
中间遇到遗忘等情况,可以回去参考教材内容,不必过分担心一开始的卡壳,高手也是这么过来的。
根据关键知识点,我选择了一些基础练习,同时列出了解题思路、问题分解以及参考代码。
大家尽量自己动脑动手完成,实在卡住进行不下去,再找答案。
查看密码在公众号“只差一个程序员了”,关注后回复关键词“练习答案”后获得。
一、基本输入输出和运算
1、输入圆的半径计算计算周长和面积
解题思路
输入:半径R
输出:周长C和面积S
关键算法:
- C=2PIR
- S=PIRR
- PI这个常量,在math库里可以引用
问题分解
- 接收输入参数:input函数
- 计算C和S:数值计算
- 输出C和S:print函数
参考代码
# coding=utf-8
"""
输入圆半径
输出圆周长和面积
Version: 0.0.1
Author : yichu.cheng
"""
import math
r = float(input('请输入圆半径:'))
c = 2 * math.pi * r
s = math.pi * r**2
print('周长:%.2f' % c)
print('面积:%.2f' % s)
2、输入三条边长,如果能构成三角形就计算周长和面积
解题思路
输入:三条边长a, b, c
输出:如果能构成三角形则输出周长L和面积S,否则输出”no”
关键算法:
- 三角形构成条件:两边之和大于第三边
- L=a+b+c
- 根据“海伦公式”,
- 其中,
问题分解
- 接收输入参数:input函数
- 判断是否构成三角形
- 计算L和S:数值计算
- 输出结果:print函数
参考代码
3、输入一个字符串,反向输出每个字符,字符间以下划线”_”相连
解题思路
输入:字符串S,如”abcde”
输出:用下划线把反向S中每个字符相连,”e_d_c_b_a”
关键算法:
- 字符串反转
- 下划线连接字符
问题分解
- 接收输入参数:input函数
- 字符串反转:借用切片反转序列(也可以用循环)
- 下划线连接字符:借用字符串的join方法
- 输出结果:print函数
参考代码
二、控制流:判断和循环
1、输入年份判断是不是闰年
解题思路
输入:年份year
输出:yes 或 no
关键算法:
- 闰年判断方式:闰年必须是4的倍数,如果它也是100倍数时,必须是400倍数,否则不是闰年。
背景介绍:
地球绕太阳运行周期为365天5小时48分46秒(合365.24219天)即一回归年(tropical year)。公历一年只有365日,比回归年短约0.2422日,所余下时间约为每四年累计一天,故第四年于2月末加1天,使当年的历年长度为366日,这一年就为闰年。现行公历中每400年有97个闰年。按照每四年一个闰年计算,平均每年就要多算出0.0078天,这样经过四百年就会多算出大约3天来。因此每四百年中要减少三个闰年。
所以公历规定:年份是整百数时,必须是400的倍数才是闰年;不是400倍数的,即使是4的倍数也不是闰年。
这就是通常所说的:四年一闰,百年不闰,四百年再闰。 例如,2000年是闰年,2100年则是平年。
问题分解
- 接收输入参数:input函数
- 计算是否是闰年:条件判断
- 输出结果:print函数
参考代码
2、百分制成绩转换为等级制成绩
成绩在90分(含)以上为A,[80-90)为B,[70-80)为C,[60-70)为D,60分以下为E。
解题思路
输入:成绩
输出:A/B/C/D/E
关键算法:
- 判断成绩区间,输出对应等级
问题分解
- 接收输入参数:input函数
- 计算所属区间:条件判断
- 输出结果:print函数
参考代码
3、输入一个正整数判断是不是素数
解题思路
输入:正整数n
输出:yes 或 no
关键算法:
- 素数:只能被1和自身整除的大于1的整数。
- 判断整数是否能被 之间的任意一个整数整除
- 优化:如果整数n可以被p1整除,商为p2,则n=p1*p2;所以只要判断 ] 间整数即可。
备注:还可以利用已发现素数的特点,来加快判断
如:质数总是等于 6x-1 或 6x+1,其中 x 是大于等于1的自然数。
首先 6x 肯定不是质数,因为它能被 6 整除;其次 6x+2 肯定也不是质数,因为它还能被2整除;依次类推,6x+3 肯定能被 3 整除;6x+4 肯定能被 2 整除。那么,就只有 6x+1 和 6x+5 (即等同于6x-1) 可能是质数了。所以循环的步长可以设为 6,然后每次只判断 6 两侧的数即可。
也就是:如果n被6除后余数不是1或5,那么它一定不是素数。
这样程序就可以通过
问题分解
- 接收输入参数:input函数
- 判断是否素数:判断 ] 任意整数是否能整除n
- 输出结果:print函数
参考代码
4、计算从1到100这一百个整数中偶数之和
解题思路
输入:无
输出:偶数之和
关键算法:
- 偶数:不能被2整除的正整数
- 把偶数循环累加
问题分解
- 生成整数序列:range函数
- 判断是否偶数:能否被2整除
- 循环累加:把偶数累加到总数变量total
- 输出结果:print函数
参考代码
**
5、输出九九乘法口诀表
解题思路
输入:无
输出:九九乘法表
关键算法:
- [1, 9]中的每个整数i,分别与[1,i]中每个整数相乘,输出对应乘法口诀
- 每个整数i单独形成一行
- 每行中的乘法口诀间,用制表符”\t”分隔
问题分解
- 生成整数i序列:range函数
- 对于每个整数i,生成整数j序列:range函数
- 输出每个i*j结果
- 为每个整数i换行
三、常用数据结构
1、输入两个英文单词,去除重复字符后,按生序输出新”单词”(不考虑词汇意义)
解题思路**
输入:2个字符串
输出:1个字符串
关键算法:
- 字符串合并:两个字符串相加
- 字符串去重和排序:借用set和sorted函数
问题分解
- 输入字符串:s1,s2
- 字符串合并:s
- 把s放入set:set内元素不重复
- 把set排序:用内置函数sorted
- 字符合并:join方法
- 输出:print函数
参考代码
2、输入一行英文句子,输出每个英文字符在其中出现的次数
解题思路
输入:一系列英文单词,以空格、”,”和”.”分隔或结尾
输出:出现的每个英文字符,及其出现次数
关键算法:
- 字符串过滤:去除非英文符号,只保留出现的[a-zA-Z]范围字符
- 字符统计:把出现过的同个字符计数
问题分解
- 输入英文句子:s
- 把句子分隔成英文单词:split方法
- 合并英文字符为新字符串s2:join方法
- 对s2生成set:set
- 分别统计set中每个字符在s2中出现次数,生成tuple list:count方法
- 输出:print函数
参考代码
**
3、从10个整数列表中最大和第二大的元素值
解题思路
输入:无,随机生成10个整数,数值范围[1,1000]
输出:最大和第二大2个整数
关键算法:
- 循环比较大小
备注:列表降序排序后前两个元素即为最大和次大元素,但排序复杂度相比循环遍历一次列表更高。
问题分解
- 生成随机整数列表:random模块的randint函数
- 循环遍历列表,找到最大和次大的两个元素值
- 输出:print函数
4、输入5个不同二维点坐标,找到直线距离最近的任意两点
解题思路
输入:5组数字,每组数字间用英文逗号分开,如”3,4”
输出:直线距离最小的两组数字
关键算法:
- 平面两点间距离公式:
- 其中两点坐标分别为:(x1, y1)和(x2, y2)
备注:
除了循环对比任意两点之间的距离,可以根据x坐标,排序后选择中位值,把点集合一分为二,采用分治法求解。
算法优化的核心在于通过证明,缩小跨集合的两点选择范围。
对算法及其证明过程有兴趣的可以搜索:“平面最近点对问题”。
问题分解
- 输入5组数字,以英文逗号分隔:split
- 转为tuple列表:tuple,list
- 循环遍历列表,计算每两组tuple的距离
- 找到最小距离的两组tuple
- 输出:print函数
参考代码
**
5、随机生成100个[-100, 100]的整数,按升序输出每个整数及其出现的次数
解题思路
输入:无,随机生成100个整数,数值范围[-100,100]
输出:每个整数及其出现次数
关键算法:
- 为每个整数计数:借助dict
备注:
第二个练习中,我们借助了string类的count方法统计字符出现次数,对于更通用的列表统计,可以参考collection包下Counter类。
问题分解
- 生成随机整数列表:random模块的randint函数
- 循环遍历列表,以整数值为key,以其出现次数为value
- 输出:print函数
参考代码
四、函数和类
1、实现计算求两个整数最大公约数和最小公倍数的函数
解题思路
输入:两个整数x和y
输出:x和y的最大公约数gcd和最小公倍数lcm
关键算法:
- 从x和y中较小的整数开始向下测试,如果都能被x和y整除,则该数为gcd(x,y)
- lcm=x*y/gcd(x,y)
备注:
欧几里得的辗转相除法:gcd(x,y)=gcd(y,x%y)
问题分解
- 定义一个函数,在程序入口处接收2个整数参数后调用
- 选择x和y中较小的整数,向下迭代寻找能同时整除x和y的整数
- 输出:print函数
参考代码
2、检查函数接受的参数,输出其类型和长度(如有)
解题思路
输入:无,随机生成一个整数,一个字符串,一个列表,作为函数参数
输出:所有参数类型,如果参数有长度则一并输出
关键算法:
- type函数判断变量类型
- len函数判断长度
问题分解
- 定义一个函数,按tuple传递参数
- 判断tuple中每个参数类型以及长度(如有)
- 输出:print函数
参考代码
3、输入一个正整数,找出以其为上限整数范围内的所有完美数
解题思路
输入:正整数n
输出:所有在[1,n]间的完美数
关键算法:
- 完美数:一个数恰好等于其真因子之和
- 比如,第一个完美数是6,6=1x2x3,且1+2+3=6
备注:
欧几里得完美数定理:如果为质数,其中p也是质数,那么便是一个完美数。
所以,可以通过质数表,加速判断算法。
第五个完美数:33550336。截至2018年,相关研究者已经找到51个完美数。
问题分解
- 定义一个函数,判断是否为完美数
- 除以每个比它小的整数,能整除的为因子
- 所有因子求和,判断是否与自己相等
- 相等则为完美数
- 循环[2,n]间所有数,分别判断
- 输出:print函数
参考代码
4、定义一个Ball类及其三个子类,分别实现3种jump方法,从子类中随机生成一批Ball实例,根据其jump方法调用结果统计各子类实例数量
解题思路
输入:无,随机生成一批实例
输出:统计生成实例所属子类数量
关键算法:
- 工厂设计模式,根据名字动态创建子类对象
问题分解
- 定义基础类Ball和3个子类
- 随机创建子类实例
- 循环调用实例jump方法,保存返回值到列表
- 根据列表统计各子类实例数量
- 输出:print函数
参考代码
5、输入一个正整数,分解其质因数,并输出
解题思路
输入:正整数
输出:分解质因数
关键算法:
- 从小到大找因数,找到后除以因数重新找
- 可以用递归和非递归解法
问题分解
- 输入正整数n
- 创建分解质因素函数
- 从[2,n]中寻找因数
- 找到后记录因数x到列表
- 继续分解n/x质因数
- 输出:print函数
参考代码
**