1、迭代法查询(顺序查找)
迭代遍历法查询无序集合非常简单粗暴,直接遍历检查是否是需要查找的值,发现等于的值后则直接返回即可,因此其时间复杂度为
private static int find(int targetValue, Integer[] numbers) {for (int i = 0; i < numbers.length; i++) {if (targetValue == numbers[i]) {return i;}}return -1;}
2、二分法查找有序集合
二分法对于查询有序集合效率非常高,其算法特别简单,但细节上可能让人错误百出,比如边界问题以及终止条件,
其时间复杂度为 第一次查询为 N/2 次,第二次查询为 N/4 次,所以当查询到元素集合等于1 的时候结束,假设执行K次,即 经过计算可知
/*** 二分法查找** @apiNote 时间复杂度: O(logN)*/private static int binSearch(int target, Integer[] nums) {int startIndex = 0, endIndex = nums.length;while ((startIndex <= endIndex)) {int minIndex = (startIndex + endIndex) / 2;if (minIndex >= nums.length) {return -1;}int mid = nums[minIndex];if (mid == target) {return minIndex;}if (target < mid) {endIndex = minIndex - 1;} else {startIndex = minIndex + 1;}}return -1;}
至于为什么 startIndex = mid + 1,endIndex = mid - 1? 这也是二分查找的一个难点,不过只要你能理解前面的内容,就能够很容易判断。需要明确了「搜索区间」这个概念,而且本算法的搜索区间是两端都闭的,即 [left, right]。那么当我们发现索引 mid 不是要找的 target 时,应该直接去掉midIndex去搜索 [left, mid-1] 或者 [mid+1, right] 对不对?因为 mid 已经搜索过,应该从搜索区间中去除
**
同样的,二分法也有缺点,比如我们需要查询出[1,2,3,3,3,4] 中3的最左边界以及最右边界,那么二分法此时是不适合的,需要经过改造下,改造的对象就在于边界上,这里不过多的赘述,有兴趣的读者可以访问 链接https://github.com/labuladong/fucking-algorithm/blob/master/数据结构系列/单调栈.md 学习
