[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第76讲。
两数之和,本题是2022年1月22日举办的第13届蓝桥杯青少组Python编程选拔赛真题编程部分第4题。题目要求对于给定的一组正整数和目标值,编程找出两个正整数,要求其和离目标值最接近。
先来看看题目的要求吧。
一.题目说明
编程实现:
给出一组正整数数据和一个正整数(目标值),从这组正整数中找出两个数,使这两个数相加后的和,小于等于目标值并且离目标值最接近,然后将两个数的和输出。
如:正整数数据为[9, 4, 3, 5],目标值为10,其中正整数数据中4和3、4和5、3和5 的和都小于目标值10,但离目标值最接近的两个数是4和 5,其和为9。
输入描述:
第一行输入一组长度大于 3 个正整数的数据(正整数 < 10000),正整数之间以一个英文逗号隔开
第二行输入一个正整数 n(1 < n < 19997),表示目标值
输出描述:
输出一个整数。
如果正整数数据中存在小于等于目标值并且离目标值最接近的两个数,则输出这两个数的和;
如果正整数数据中不存在这样的两个数,即正整数数据中任意两个数的和都超过了目标值,则输出-1
样例输入:
9,4,3,5
10
样例输出:
9
二.思路分析
这是一道简单的算法题,涉及的知识点包括循环、条件语句和列表等。
对于本题,最简单的方法就是暴力枚举,就是将所有的组合列举出来并求和,然后和目标值进行比较,在小于等于目标值的和中,找到最大的那个和。
计算两个数的组合之和,可以采取如下两种方式:
-
嵌套循环
-
使用combinations()函数
只是,使用这两种方法的时间复杂度都是O(n2),如果要降低时间复杂度,可以使用双指针算法。
所谓双指针是指在遍历列表的过程中,不是使用单个指针进行访问,而是使用两个指针进行访问,从而达到相应的目的。
最简单的双指针是对撞指针,它指的是使用两个指针left、right分别指向列表第一个元素和最后一个元素,然后left指针不断递增,right不断递减,直到两个指针的值相撞(即 left== right),或者满足其他要求的特殊条件为止。
双指针利用了区间单调性的性质,可以将时间复杂度降到 O(n)。
思路有了,接下来,我们就进入具体的编程实现环节。
三.编程实现
根据上面的思路分析,我们使用三种方法来编写程序:
-
枚举算法
-
使用combinations()函数
-
双指针算法
1. 枚举算法
根据前面的思路分析,我们使用嵌套循环编写代码如下:
代码不多,说明两点:
1). res表示最终的结果,初始值为-1,如果不存在小于target的情况,就直接输出-1;
2). 注意i和j的范围,前者从0开始到len(nums) - 1,后者从i+1开始,一直到最后一个列表项。
2. 使用combinations()函数
combinations()函数可以帮我们生成所有可能的两个数的组合,原来的两层循环可以简化为一层,对应的代码如下:
要使用combinations()函数,必须先导入。
3. 双指针算法
根据前面的思路分析,编写代码如下:
代码稍微要复杂一点,简单说明两点:
1). 使用双指针算法,要确保nums列表是有序的;
2). 当left < right,计算两数之和,并不断调整left和right指针,当两个指针撞到一起了,循环结束。
至此,整个程序就全部完成了,你可以输入不同的数字来测试效果啦。
四.总结与思考
本题代码在10行左右,涉及到的知识点包括:
-
循环语句;
-
列表操作;
-
输入输出处理;
-
组合函数;
本题代码不多,难度中等,关键点是要理解题目的意思,这里要寻找小于等于target的两数和,并且是最接近target的。小于等于target的两数和可能有很多个,所谓最接近target,就是在满足条件的两数和中找最大的。
在计算机编程中,最常用的算法就是暴力枚举,这也是计算机最擅长的事情。
但是,暴力枚举要将所有的情况都列举出来,随着数据规模的增加,时间复杂度会急剧增加。因此,我们需要寻找更聪明的枚举方法,根据不同的问题和场景,可以采取不同的优化策略,也就产生了各种不同的算法。
本题中的双指针算法就是一个非常好的优化技巧,在编程中会经常用到,比如字符串反转、判断回文数和快速排序等。
你还有什么好的想法和创意吗,也非常欢迎和超平老师分享探讨。
如果你觉得文章对你有帮助,别忘了点赞和转发,予人玫瑰,手有余香😄
需要源码的,可以移步至“超平的编程课”gzh。