利用二分查找法来解一道列表排序题
Posted 娜驿站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用二分查找法来解一道列表排序题相关的知识,希望对你有一定的参考价值。
前言
Python
中,有一个标准模块叫bisect
,它很好地实现了二分查找,并对边界情况进行了处理,所以,对于Python
用户而言,直接利用这个模块进行相应的操作,就会显得非常方便。
leetcode
时,碰到这样一道题目,它初看起来不难,但仔细思考却发现里面有很多陷阱,不过如果能利用好二分查找这一工具,那这道题目就迎刃而解。
有一个列表,它的每个元素都是有序整数数对,其形式如 [[a1,b1], [a2,b2], [a3,b3],...[an, bn]]
,根据数的大小可知,在其中总会找到一个子集[[ai1, bi1], [ai2, bi2], [ai3, bi3],..., [aim, bim]]
,使得该子集中的元素满足ai1<ai2<ai3<...<aim
且bi1<bi2<bi3<...<bim
。现在要问的是,在这所有符合条件的子集中,其长度最长会是多少?
[[5, 4], [6, 4], [6, 7], [2, 3]]
,在其中[[2, 3], [5, 4], [6, 7]]
是最长的符合要求的子集,因此最长的子集长度是3。
Python
中的bisect
标准库。
bisect
标准库
bisect
标准库主要实现二分查找功能,它其中包含六个函数,分别是bisect, bisect_left, bisect_right, insort, insort_left, insort_right
,其中bisect
是bisect_right
的简写形式,insort
是insort_right
的简写形式,所在,从实际上来说,该标准库只有四个不同的函数。下面我们来一一说明。
[0, 1, 2, 3, 4, 5]
中查找
1
这个元素,结果查找到了
1
位于数组的第1位(数组从0开始计位),所以它直接返回该位置,如果用函数
bisect_right
,则会返回
1
的下一个位置2:
insort_left
是插入同数左侧,而insort_right
则是插入同数右侧,但这两种区别仅限于内部运行,对于外在表现而言,两者相同:
[[5, 4], [6, 4], [6, 7], [2, 3]]
为例来说明。
[[2, 3], [5, 4], [6, 4], [6, 7]]
[6,7]
放在[6,4]
前面,则更容易找到找出符合条件的子集,因此我们在上述排序的基础上,在第一个数相同的有序数对中,再以第二个数的降序进行排列,这样的结果如下:
[[2, 3], [5, 4], [6, 7], [6, 4]]
arr3
,然后用birect.birect_left
在arr3
中查询这些有序数对的第二个数,如果得到的位置等于arr3
的长度,则说明找到了新的值,将其加入arr3
,否则只需要将arr3
中相应位置进行更换即可,代码如下:
dp
存放的并不一定是真实符合条件的子集中数对的第二个数集合,它只是对有序数对第二个数的一种查找和替换,其长度说明了在这个已经按有序数对第一个数排好序的列表中,含有这么个长度的符合条件的子集而已。
小结
Python
的一个标准模块,这个问题并不容易理解,在此记录仅供备忘和大家参考。
以上是关于利用二分查找法来解一道列表排序题的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode Binary Search Summary 二分搜索法小结