Binary Search的基础框架代码
Bianry Search的基本思想
二分查找法是基于一组有序数上的查找,它的时间复杂度最坏为O(n),平均时间复杂度为O(lgn),空间复杂度为O(1)。由于它不需要借助额外的空间,并且大多数情况下(平均)性能较好,所以是应用较广的一种查找法。
接下来介绍一些其他查找方法的时间和空间复杂度:
查找算法 | 平均时间复杂度 | 最坏时间复杂度 | 空间复杂度 |
---|---|---|---|
顺序查找 | O(n) | O(n) | O(1) |
二分查找 | O(lgn) | O(n) | O(1) |
二叉树查找 | O(lgn) | O(lgn) | O(n) |
哈希查找 | O(1) | O(1) | O(n) |
二叉树查找需要在原有数据的基础上建立二叉排序树,因此需要额外的空间,比较适合多次连续查找。类似的算法有哈希查找,需要额外空间建立哈希表,同时考虑冲突处理等问题。
可以看出,二叉查找是比较适合不知道查找次数的情况。因为他不需要建立额外储存结构。
Bianry Search的基础框架代码
该代码为实现在有序数组中查找某个目标数的基本框架,与二叉查找有关的其他题型可在此框架上进行修改。
public int findPosition(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0, end = nums.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
start = mid;
} else {
end = mid;
}
}
if (nums[start] == target) {
return start;
}
if (nums[end] == target) {
return end;
}
return -1;
}
该代码搜索位置比较偏左,搜索到的目标数可能的第一个位置为start。
Binary Search的相关题型
Search Insert Position
题目为搜索目标数第一个出现的位置,如果找不到则返回其应该插入的位置。
换种思路可以有:搜索源数组里第一个大于等于目标数的位置,或者最后一个小于目标数的位置+1。这两种思想需要充分利用start和end的位置关系。
Search a 2D Matrix I
题目为在一个二维数组中搜索目标数。
解题思路有以下两种:
- 由于二维数组里的数是严格递增的,因此可以将二维数组看成一维数组进行搜索,每个数的下标可以看成是i×n+j。使用matrix[mid / column][mid % column]与目标数进行对比。
- 可以先搜索行,再搜索列。注意搜索行的时候,去寻找第一个小于等于matrix[mid][0]的数,该数所在的行数即为所要找的行数。因此,退出循环之后要先与matrix[end][0]进行对比。
Search a 2D Matrix II
题目为写出一个高效的算法来搜索m×n矩阵中的值,返回这个值出现的次数。这个矩阵具有以下特性:
- 每行中的整数从左到右是排序的。
- 每一列的整数从上到下是排序的。
在每一行或每一列中没有重复的整数。
该二维数组中的数并不是严格递增的,因此不适合上题中的方法。但其可以看成是是在二维坐标轴中进行向右或向上的行走。即初始时在左下角逐渐向右上角进行搜索。代码片段:
while (x >= 0 && y < m) {
if (matrix[x][y] < target) {
y++;
} else if (matrix[x][y] > target) {
x--;
} else {
count++;
x--;
y++;
}
}
Find Peak Element
题目为返回任意一个峰值的位置。因此,应使A[mid]与A[mid + 1]和A[mid - 1]进行比较,最后的结果在A[start]和A[end]之间,所以还需要进行最后一次判断,返回较大者。
First Bad Version
该题需要返回第一个错误的版本,要求调用次数较少。调用次数可以看成比较次数,某种意义上说也是时间复杂度,因此使用二分查找很合适。使用上述框架,则可以考虑成寻找第一个位置上的SVNRepo.isBadVersion(mid)为ture的值。