文章目录
- 二分查找简介
- 实现方式
- 循环方式
- 递归方式
- 经典例子
二分查找简介
- 二分查找(binary search)算法,也叫折半算法。
- 二分查找是针对有序的数据集合的查找办法,如果是无序的数据结合就使用遍历。
- 二分查找之所以快速,是因为它再匹配不成功的时候,每次都能排除剩余元素中一半的元素,因此包含目标元素的有效范围就会收缩非常快。
- 时间复杂度: T(n) = O(logn)
实现方式
循环方式
package com.xxliao.algorithms.binary_search.demo;/*** @author xxliao* @description: 在一个有序集合中,查找某数是否存在 -- 基础实现* @date 2024/5/30 0:40*/
public class Demo01 {public static void main(String[] args) {//有序数组int[] nums = {3, 12, 24, 31, 46, 48, 52, 66, 69, 79, 82};System.out.println(binarySearch(nums,66));System.out.println(binarySearch(nums,55));}/*** @description 二分法基础实现* @author xxliao* @date 2024/5/30 0:47*/public static int binarySearch(int[] array,int destNum) {// 低索引int low = 0;// 高索引int high = array.length -1;// 中间索引int mid = 0;while(low<=high) {mid = (low + high) / 2;if(array[mid] == destNum) {return mid; //相等,找到该索引}else if(destNum < array[mid]){high = mid - 1; // 比中间值小,}else{low = mid + 1; // 比中间值大}}return -1;}
}
测试结果:
递归方式
package com.xxliao.algorithms.binary_search.demo;/*** @author xxliao* @description: 在一个有序集合中,查找某数是否存在 -- 递归实现* @date 2024/5/30 0:40*/
public class Demo02 {public static void main(String[] args) {//有序数组int[] nums = {3, 12, 24, 31, 46, 48, 52, 66, 69, 79, 82};System.out.println(binarySearch(nums,48));System.out.println(binarySearch(nums,55));}/*** @description 二分法 递归实现* @author xxliao* @date 2024/5/30 0:47*/public static int binarySearch(int[] array,int destNum) {// 低索引int low = 0;// 高索引int high = array.length -1;return binarySearch(array,low,high,destNum);}private static int binarySearch(int[] array,int low,int high,int destNum){//定义递归结束条件if(low > high)return -1;int mid = (low + high) / 2;if(array[mid] == destNum) {return mid; //相等,找到该索引}else if(destNum < array[mid]){high = mid - 1; // 比中间值小,}else{low = mid + 1; // 比中间值大}return binarySearch(array,low,high,destNum);}
}
测试结果:
经典例子
一个有序数组有一个数出现1次,其他数出现2次,找出出现一次的数
比如:1 1 2 2 3 3 4 4 5 5 6 6 7 出现1次的数是7。
使用二分查找: 1 有序、 2、时间复杂度 O(logn)。
偶数位索引跟后面的比相同,奇数位索引跟前面的比相同 则说明前面的都对。
偶数位索引跟前面的比相同,奇数位索引跟后面的比相同 则说明后面的都对。
package com.xxliao.algorithms.binary_search.demo;/*** @author xxliao* @description:* 一个有序数组有一个数出现1次,其他数出现2次,找出出现一次的数* 比如:1 1 2 2 3 3 4 4 5 5 6 6 7 出现1次的数是7** 使用二分查找: 1 有序、 2、时间复杂度 O(logn)* 偶数位索引跟后面的比相同,奇数位索引跟前面的比相同 则说明前面的都对* 偶数位索引跟前面的比相同,奇数位索引跟后面的比相同 则说明后面的都对** @date 2024/5/30 1:06*/public class Demo03 {public static void main(String[] args) {int[] nums={1,2,2,3,3,4,4,5,5};//int[] nums = {1,1, 2, 2, 3, 4, 4, 5, 5,6,6,7,7};System.out.println(binarySearch(nums));}public static int binarySearch(int[] nums) {//低位索引int low = 0;//高位索引int high = nums.length - 1;//中间索引int mid = 0;while (low < high) {mid = (low + high) / 2;if (mid % 2 == 0) {//偶数位if (nums[mid] == nums[mid + 1]) {// 与后面的数相等,前面的都对low = mid + 1;} else if (nums[mid] == nums[mid - 1]) {// 与前面的数相等,后面的都对high = mid - 1;} else {// 就是这个数return nums[mid];}} else {//奇数位if (nums[mid] == nums[mid - 1]) {// 与前面的数相等,前面的都对low = mid + 1;} else if (nums[mid] == nums[mid + 1]) {//与后面的数相等,后面的都对high = mid - 1;} else { // 就是这个数return nums[mid];}}}//low=highreturn nums[low];}
}
测试结果: