出场人物介绍:
小美:小学4年级学生,参加了学校的编程兴趣小组,已经了解了Python语言的基本语法,能够看懂一些简单的程序。她做事风风火火,对所有的事情都很好奇,喜欢打破砂锅问到底,是一个叫人又爱又恨的小丫头。
阿福:一个酷爱编程的8年级男生。大家都说他长得像国宝大熊猫,动作缓慢,憨态可掬。他做事情确实够慢的,连说话也慢条斯理,可是他一点也不担心,他常常说:“慢就是快,只要坚持下去,蜗牛也能爬上金字塔。”
古老师:虽然年近不惑,但依然对生活充满热情。“爱生活爱运动”是他的人生信条,和孩子们一起编程是他最大的乐趣。他神出鬼没,总是在孩子们最需要帮助的时候出现。当然,你也不能动不动就找古老师,因为他很忙,非常非常忙。所以,遇到问题还是自己先思考吧。
正文
列表的纷争之双指针扫描
小美:最近我们学习了一种新的数据结构——列表。列表比字符串灵活多了,它不仅可以修改元素值,还可以随意增加和删除元素,功能十分强大。
阿福:是啊,列表是Python语言中使用非常广泛的一种数据结构,它的内置函数很丰富,功能十分强大。
小美:列表的内置函数确实太“丰富”了,我怎么也记不住。对了,阿福你是怎么记住这些函数的呢?
阿福:我也没什么好的方法,就是多记多用呗。
古老师:没错,学习不能老想着走捷径!成功的秘诀就是熟能生巧。不过要想深刻地理解Python的内置函数,除了多运用它们解决实际问题以外,尝试自定义函数来实现相同的功能也是一种很好的方法。
小美:自定义函数?
阿福:用户自己创造的用来实现某种特定功能的函数就叫自定义函数。
古老师:阿福说的没错。那我今天就来考考你们,能否编写一个自定义函数来实现列表中reverse()方法的功能。
知识小贴士:
Python3 List reverse()方法:reverse() 函数用于反向列表中元素。它的语法是list.reverse(),该方法没有形式参数,也没有返回值,但是会对列表的元素进行反向排序。
小美:这有什么难的,看我的!
问题1:
反向列表中元素
函数功能:将输入的列表的元素进行反向排序
函数名:my_reverse(a:list) -> None
参数表:a -- 列表。
返回值:该函数没有返回值,但是会对列表a的元素进行反向排序。
示例:输入a=[1,6,5,2],函数运行后a=[2,5,6,1]
代码1:
defmy_reverse(a: list) -> None:
n = len(a)
for i in range(n//2):
a[i], a[n-i-1] = a[n-i-1], a[i]
阿福:我也写好了。
代码2:
defmy_reverse2(a: list) -> None:
L, R = 0, len(a) - 1
while L < R:
a[L], a[R] = a[R], a[L]
L, R = L + 1, R – 1
古老师:都很棒!小美使用单指针扫描技术,分别用a[i]和a[n-i-1]来表示两个对称的元素,让它们进行交换操作,这样只需使用一个循环变量扫描半个列表,代码简洁,效率也很高。但我更推崇阿福的做法,他使用了所谓的双指针扫描技术,分别用L和R两个变量从两边向中间扫描,直接交换a[L]和a[R],直到L和R相遇。这种做法思路非常清晰,代码的含义也很明确,是可读性很强的代码。
阿福:谢谢老师夸奖!呵呵。
小美:看你美的!不就是双指针吗?功能还不是和我的单指针一样?说不定效率还没有我的高呢!
古老师:小美你还别不服气,双指针扫描确实是一种既好看又实用的方法,很多时候它能完成单指针所做不到的事情。比如下面这个例子:
问题2:
奇偶数分组
函数功能:将输入的列表元素按照奇偶性分组,其中奇数划到左侧,偶数划到右侧
函数名:group(a: list)-> None
参数表:a -- 列表。
返回值:该函数没有返回值,但是会对列表a的元素按照奇偶性分组。
示例:输入a=[1,6,5,2],函数运行后a=[1,5,6,2]
小美:奇偶数分组?要用到双指针扫描?该怎么做呢?
古老师:又到了说再见的时候了。你们先自己想想看吧,实在做不出再来找我,先走了,拜拜。
彩蛋:
小美:古老师每次都卖关子。阿福,你想到办法了吗?
阿福:有点思路了,好像跟反转列表的方法差不多,但这里需要用到二重循环,否则不好表达。小美,你知道二重循环吗?
小美:知道啊,不就是循环里面套循环嘛。
阿福:知道就好,我还怕你看不懂我写的程序呢。你看:
代码3:
def group(a:list) -> None:
L, R = 0, len(a) - 1
while L < R:
while a[L] % 2 == 1: #跳过左侧的奇数
L += 1
while a[R] % 2 == 0: #跳过右侧的偶数
R -= 1
if L < R:
a[L], a[R] = a[R], a[L]#将元素交换到正确的一侧
L, R = L + 1, R - 1 #交换好后各自前行一步,效率更高
网友评论