Python数据结构与算法——第十八课 数组支点/幸运值/二分法

  例题1:求一个数组的支点元素。

  一个数组由正负整数或0构成,在数组中(头尾元素除外)找到一个元素(支点),让元素左侧子数组之和与右侧子数组之和相等(不包含元素本身),返回这个元素的下标。如果无此种元素,返回-1,如下图所示。

 

  解题思路分析:从下标1开始循环遍历,左侧子支点数组循环求和,右侧子数组循环求和,两和相等则此下标所在元素是支点元素(此支点元素本身不参与左,右数据求和运算)。一个数组中可能有1个支点,也可能有多个,或者一个也没有。如果循环到数组右侧倒数第2个元素的位置还没有发现支点,则说明此数组无支点。为了简化运行,把第一个元素分为左组,其它元素分右组,右元素计算总和。循环体内右组减去一个元素后与左组比较决定这个元素是否是支点元素,然后把这个元素加到左组。

  程序代码:

 

 

  运行结果:

 

 

  练习题1:求下面数组中相邻的两个数(含头尾)的下标,使以这两个数为分界的两部分的和相等(两个数一个一边参与求和运算)。

[4,6,-88,23,17,-30,29,-100,65,-45,30,-47]

 

  例题2:求数组的幸运值。

  一个数组由0~9的整数构成,6,8,9为幸运数,遇到这些幸运数则幸运值加14为不幸数,遇到此不幸数则幸运值减1;但如果04的左侧,04转为幸运数,幸运值反加1,同理,6,8,9左侧如果有0,均变成不幸数,幸运值减1。如下图所示数组的幸运值。

 

  解题思路分析:用两个临时变量分别储存当前指针所指向元素的前1个元素和一个数的幸运值,如果这数是6,8,9则给幸运值加1,遇不幸数4则减1;如果前一个数为0,幸运值取反。幸运值增减如下图所示。

 

  程序代码:

 

 

  运行结果:

 

 

  练习题2:上一例题中,如果这个数的前两个数之和是偶数侧幸运值取反,修改程序计算它的幸运值。

 

  例题3:在数组中实现二分法查找。

  在一个有序数组中查找一个数,如果找到此数则获取此数的下标(在数组中的序号),如果不存在此数,则返回-1

  解题思路分析:一般的思路是在数组中循环查找,直到找到与目标数相同的数为止。但当数组非常大时,尤其还是有序的数组时,顺序查找就比较费时了。二分法查找采取两边取中法,逐步夹逼定位待查数字,效率要高很多。

  其步骤是:声明左、右两个边界,初始化时左边界在数组0下标位置,右边界在数组最右侧节点位置。然后计算左、右两个下标的中点位置(右边界一左边界除以2并向下取整),取中点数与待查数比较,如果待查数更小,则右边界移动到中点位置,若更大,则左边界移动到中点位置。然后重新计算左、右边界的中点位置,如此循环,直到找到待查数在数组中的序号。链表由于需要从头指针循环到下标所在位置,二分法查找在链表中的查找速度并不快;但在数组中的查找速度却非常快(数组是通过下标直接定位的)。在数组中实现二分法查我算法的图解分析如下图所示。

 

  由以上步骤得知,在二分法查找中,p指针只需移动4次即可找到所查数值。在数据量的数组中查找效率要远高于普通的循环遍历。

  程序代码:

 

 

  运行结果:

 

 

  练习题3:查找下面有序数组中相邻两个整数和是99的两个下标。

[1,3,7,8,9,14,20,21,28,34,37,45,54,63,69,77,81,93,108]

 

  学思营编程课堂基于蓝桥STEM86平台https://www.stem86.com,开展学编程三部曲:Scratch(三年级以前)>>>Python(四年级以后)>>>C++(七年级以后)教育实验活动,任何人可以免费参加,打开https://xuesiying.stem86.com网页注册进入课堂,也可关注本公众号留言。更多课程请打开学思营同步网站:http://www.5xstar.com/doc.html

 

 

参考资料:

1、《Python算法图解》何韬编著 清华大学出版社