简单练习题
python练习题—求三位数组合
lst = [3, 6, 2, 7] |
这四个数字能组成多少个互不相同且无重复数字的三位数?比如362算一个,326算一个,请逐个输出他们
思路分析
从4个数字里挑出来,组成一个3位数,就算法而言,最方便的做法是用一个3层嵌套循环,分别从lst取数,取出来的数值组成一个3位数,题目要求无重复数字,这就要求,取出来的3个数字互不相等
示例代码
lst = [3, 6, 2, 7] |
如何判断3个数值互不相等,还有一个更简单的办法
if a not in (b, c) and b != c: |
生成矩阵
题目要求
已知两个列表
lst_1 = [1, 2, 3, 4] |
请写算法,将两个列表交叉相乘,生成如下的矩阵
[['1a', '2a', '3a', '4a'], |
思路分析
观察生成的矩阵,可以得出这样的结论,lst_1的长度决定了矩阵有多少列,lst_2的长度决定了生成的矩阵有多少行。
既然是交叉相乘,那么可以写两个for循环,嵌套遍历这两个列表,对lst_2的遍历放在外层,对lst_1的遍历放在内层。
示例代码
import pprint |
python练习题-列表偏移
题目要求
lst = [1,2,3,4,5],列表向右偏移两位后,变成lst = [5,4,1,2,3]
思路分析
先说简易思路,以向右偏移2位做例子,直接对列表进行切片操作,然后再讲切片后的列表连接在一起
lst = [1,2,3,4,5] |
如果是初学者这样做,是完全可以接受的,但如果想更上一层楼,则需要更加合理的解决方法
首先,偏移的位数可能会超过列表的长度,比如向右偏移47位,此时,就要考虑用47%5 = 2,向右偏移47位等价于向右偏移2位
直接对列表进行切片操作,终究还是用了列表的原生功能,既然是练习题,且偏向于算法层面,那么我们应该自己来实现偏移,不生成新的列表,只在原列表上动手脚
不论偏移多少位,在实现时,每一次,我们只偏移1位,先实现偏移1位的情况。
偏移1位,只需要将列表最后一位记录下来,然后其他所有位置上的数值向右移动一位,最后将之前记录下来的列表最后一位放置在列表的开头即可。
实现了偏移1位,剩下的仅仅是写一个for循环,就可以偏移指定的位数
示例代码
lst = [1,2,3,4,5] |
python练习题-随机数生成与遍历
题目要求
生成有100个随机正整数的列表,随机数小于1000,遍历列表,删除其中的素数,然后输出最大值,将剩余数值降序输出
思路分析
随机数的生成需要使用random模块
lst = [random.randint(2, 999) for i in range(100)] |
素数,是大于1的数,除了1和自身,没有其他的因数,大白话就是除了1和自身,除以其他的数都得不到整数结果
假设一个数值是M,那么从2开始到M//2 ,用M逐个对这些数取模,如果得到0,就说明可以整除,M就不是素数
为啥只遍历到M//2 呢,因为大于M//2的数,除了M意外,其他的肯定不能被整除,简单的数学知识,不必再解释
def is_prime(number): |
想要删除素数,千万不能这么写
for number in lst: |
在使用for循环对列表进行遍历时,本质上是在根据数据的索引获取数据,如果使用remove方法删除的某个数据,那么被删除的数据后面的数据的索引都发生了改变,会影响for循环,导致紧挨着你删除的数据的下一个数据无法遍历到,下面的这个例子可以很清楚的观察到这个情况
lst = [2, 4, 6, 8, 10, 12] |
不能用remove,咋办呢,可以使用列表推导式,也可以使用一个新的列表来存储非素数
lst = [item for item in lst if not is_prime(item)] |
或者
new_lst = [] |
最后找出列表最大值,可以使用max内置函数,也可以对列表进行排序,从大到小
完整示例代码
import random |
python练习题-寻找列表里第二大的数
题目要求
实现算法,查找列表里第二大的数
lst = [3, 6, 7, 9, 2] |
思路分析
最直接的方法是使用列表的sort方法,从小到大排序,lst.sort(),lst[-2] 就是列表里第2大的数。
能想到这个处理方法,对初学者来说,很好了,如果要求算法复杂度为O(n) 呢? 显然,排序算法都不符合要求。
找列表里最大值,只需要遍历一遍列表就可以实现,算法复杂度是O(n), 能否以此为基础,顺带手的找出列表里第2大的数呢?
设置两个变量,max_value,sec_max_value,分别表示列表里的最大值和第2大的值,遍历列表,分别于他们比较并进行替换,
示例代码
lst = [3, 6, 7, 9, 2] |
python练习题-startswith
题目要求
实现函数is_startswith,如果字符串source是以substr开头的,则函数返回True,反之返回False
def is_startswith(source, substr): |
思路分析
函数首先要判断传入的参数是否合法,这里默认传入的都是字符串,那么我们要需要判断字符串是否有空串的情况
如果substr的长度大于source的长度,直接返回False
从索引0开始,遍历substr,从source上获得相同索引的字符,两者进行比较,只要有一个字符不相同,则可以立即返回False
示例代码
def is_startswith(source, substr): |
python练习题-统计字符数量
题目要求
使用input函数接收用户的输入,统计出其中英文字母、空格、数字和其它字符的个数,例如用户输入字符串”sdfijer384323js”,程序最终输出信息
{'s': 2, 'd': 1, 'f': 1, 'i': 1, 'j': 2, 'e': 1, 'r': 1, '3': 3, '8': 1, '4': 1, '2': 1} |
思路分析
input函数接收用户的输入,得到的是字符串,遍历字符串,统计字符串中每一个字符出现的次数,这种信息自然是用字典来存储,其他容器类型数据列表,元组,集合,都不适合存储这种key-value形式的数据
示例代码
string = input("请输入一个字符串:") |
忽略大小比较字符串是否相等
题目要求
比较两个字符串,忽略大小写,比如字符串”abc”和字符串”ABC”,在忽略大小写的情况下是相等的,实现函数
def is_same_ignore_case(str1, str2): |
要求,不能使用字符串的lower方法和upper方法
思路分析
题目要求不能使用字符串的lower方法和upper方法,之所以这样要求,是希望你能从更基础的编程做起,培养更深入的思考。
要解这个练习题,你需要对ASCII码表有一定的了解,在ASCII码表中,大小写字母的十进制编码相差32。
通过for循环,遍历str1,同时获取与之相对应索引上的字母,因为要忽略大小写,因此,将他们都转换成ASCII码表里的十进制数值,并且统一转成小写字母的十进制数值。
在进行正式比较前,严谨的判断逻辑应该是先判断传入的参数str1和str2是否有效,然后判断这两个字符串的长度是否相等,这些都是从程序的健壮性和效率上考虑的。
enumerate函数是一个非常方便且有用的函数,在for循环中,既能获得遍历的元素,又能获得该元素的索引。
示例代码
def get_ord_value(string): |
计算三角形的周长和面积
题目要求
写一段程序,让用户输入三角形的三条边长,如果三条边长不能构成三角形,则提示用户重新输入
如果可以构成三角形,则计算周长和面积
思路分析
对于用户的输入,首先要约定格式,这里简单的约定为每个边长之间用空格间隔
在获得用户的输入以后,要对输入进行检查,有两点需要检查
(1) 检查是不是输入了三条边的边长,输入2个或者4个都是错误的
(2) 检查输入的内容是不是数值型,如果输入的是字母,那根本驴唇不对马嘴
以上两点是编程时要考虑的,经过上面的分析你应该有所体会,编程,并不是你掌握一门语言然后用它在计算机上做各种操作
编程,是对问题的思考,我这里约定让用户一次性输入三条边的边长,中间用空格隔开,你也可以让用户输入三次,也可以让用户输入一次但用别的字符做间隔,这些都是没有定论的,完全取决于你的思考
对于输入内容检查,你可能会以为python会自己完成,但其实不会,input获得的就是字符串,你必须理解什么是字符串,必须清楚的知道input的作用,这些都是最最基础的内容,如果你不掌握这些,那你就无法思考
根本不存在一种方法或者操作可以满足你的要求,可以解决实际的问题,编程就是分析问题然后你自己解决问题的过程
def get_edge(line): |
打印杨辉三角
题目要求
给定一个正整数N,打印杨辉三角的前N行
杨辉三角形态如下
1 |
杨辉三角的每一行第一个和最后一个元素都是1
中间的元素,由上一行的两个元素相加得到,第N行的第index元素
是由第N-1 行的第index-1元素和第index相加得到的
思路分析
- 杨辉三角的每一行的第一个元素和最后也元素都是1
- 中间的元素可以由上一行的元素两两相加得到
第N行元素,可以由第N-1 行变化而来,这正是递归算法的精髓,把新的问题转化成老的问题,而老的问题转化成更老的问题,最终必然有一个老问题给出答案,然后整个逻辑链条上的问题都有了答案
代码示例
def print_yanghui(n): |