本文简述二分查找算法与经典算法题。
二分查找最重要的特点要求是查找的序列有序,这样可在时间复杂度logn
的情况下查找到目标值。
但是二分查找的题目变化比较多,可能会要求查找满足条件的最小值,满足条件的最大值。
有的数组序列虽然有序,但是可能存在重复值。
有的不直接告诉咱们数组序列是有序的是,而是需要自己去发现。
基础的二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
1 | class Solution { |
变化的二分查找
搜索旋转排序数组
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
这道题的细节部分比较多。
最重要的需要理解这么一句话:
1 | 将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。 |
1 | class Solution { |
求最小的最大值或者 最大的最小值 类题目时首先想到二分查找
礼盒的最大甜蜜度
给你一个正整数数组 price ,其中 price[i] 表示第 i 类糖果的价格,另给你一个正整数 k 。
商店组合 k 类 不同 糖果打包成礼盒出售。礼盒的 甜蜜度 是礼盒中任意两种糖果 价格 绝对差的最小值。
返回礼盒的 最大 甜蜜度。
题意 -> 给定一个数组,选择任意 K 个数组成一个新集合,一个集合的有效值为 集合 所有任意两个数之差的绝对值 中取最小值,返回最大有效值集合的值。
「任意两种糖果价格绝对差的最小值」等价于「排序后,任意两种相邻糖果价格绝对差的最小值」。
如果题目中有「最大化最小值」或者「最小化最大值」,一般都是二分答案,请记住这个套路。
由于数组中任意元素都是大于0的,因此最小的有效值肯定是 0, 而最大的有效值肯定是排序之后的数组中 最后一个元素 - 第一个元素 之差,假设为 x。 因此答案肯定在 0-x 之间。
题意 -> 在 0-x 中找一个最大值 -> 很显然二分查找最合适不过了,因为 0-x 是有序的,完全满足二分查找条件。
还有一个问题,如何判断 0-x 中的 mid 是否满足题意有效:
mid的含义为 数组中集合有效值为mid的个数 >= K,因此只需要判断数组中是否存在 K 个以上集合有效值大于等于 mid。
不需要枚举所有集合的有效元素,由于数组已经升序处理,只需要判断具体有多少集合是满足要求即可,具体判断方法请看代码。
1 | class Solution { |
两球之间的磁力
在代号为 C-137 的地球上,Rick 发现如果他将两个球放在他新发明的篮子里,它们之间会形成特殊形式的磁力。Rick 有 n 个空的篮子,第 i 个篮子的位置在 position[i] ,Morty 想把 m 个球放到这些篮子里,使得任意两球间 最小磁力 最大。
已知两个球如果分别位于 x 和 y ,那么它们之间的磁力为 |x - y| 。
给你一个整数数组 position 和一个整数 m ,请你返回最大化的最小磁力。
1 | class Solution { |