二分搜素算法
二分搜索算法的三种情况
推荐博客,真的写的非常好!!!
1、当数组中没有重复元素时:
public int binarySearchImplement(int[] array, int target) { if (array == null || array.length == 0) return -1; int start = 0, end = array.length -1; int index = -1; boolean flag = false; while (start <= end) { // <= 表示左闭右闭的区间 //int mid = (start + end) >> 1; int mid = start + (end - start) /2; //这样写是为了防止加法溢出 if (array[mid] == target) { index = mid; flag = true; break; } else if (array[mid] > target) { end = mid-1; } else { start = mid + 1; } } if (flag) return index; else return -1; }
2、当数组中有重复元素,寻找左边界
public int binarySearch_leftBound(int[] array, int target) { if (array == null || array.length == 0) return -1; int start = 0, end = array.length; //左闭右开 => [0, length) while (start < end) { //终止条件为: (start = end) => [start, start) int mid = start + ((end - start) >>> 1); //移位运算的优先级小于加法,所以别忘了加括号 if (array[mid] == target) { end = mid; } else if (array[mid] < target) { start = mid + 1; //搜索区间变为[mid+1, end) } else if (array[mid] > target) { end = mid; //搜索区间变为[start, mid) } } if (start == array.length) return -1; return array[start] == target? start: -1; //start = end,也可以写成return end }
3、当数组中有重复元素,寻找右边界
public int binarySearch_rightBound(int[] array, int target) { if (array == null || array.length == 0) return -1; int start = 0, end = array.length; //左闭右开 => [0, length) while (start < end) { //终止条件为: (start = end) => [start, start) int mid = start + ((end - start) >>> 1); //移位运算的优先级小于加法,所以别忘了加括号 if (array[mid] == target) { start = mid + 1; //向右边搜索 } else if (array[mid] < target) { start = mid+1; //搜索区间变为[mid+1, end) } else if (array[mid] > target) { end = mid; //搜索区间变为[start, mid) } } if (start == 0) return -1; return array[start-1] == target? (start-1): -1; }
import org.junit.Test; public class NC105 { @Test public void test() { int[] nums = {2,2}; int target = 2; System.out.println(search_3(nums, target)); } // 当数组中无重复元素 public int search(int[] nums, int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length - 1; // 搜索区间是左闭右闭[0, len-1] while (left < right) { // 停止条件[left, left],left没有判断,最后要特判(while必须能停下来) int mid = left + ((right - left) >> 1); if (nums[mid] == target) { return mid; } else if (nums[mid] < target) { left = mid + 1; } else if (nums[mid] > target) { right = mid - 1; } } return nums[left] == target? left: -1; // 这里加一下对left的判断 } // 当数组中无重复元素 public int search_1(int[] nums, int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length - 1; // 搜索区间是左闭右闭[0, len-1] while (left <= right) { // 停止条件[right+1, right],搜索区间就都为空了,这里就不用特判 int mid = left + ((right - left) >> 1); if (nums[mid] == target) { return mid; } else if (nums[mid] < target) { left = mid + 1; } else if (nums[mid] > target) { right = mid - 1; } } return -1; } // 当数组中有重复元素,寻找左边界 public int search_2(int[] nums, int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length; // 左闭右开[left, right) while (left < right) { //[left, left) [2,2) int mid = left + ((right - left) >> 1); if (nums[mid] < target) { left = mid + 1; } else if (nums[mid] > target) { right = mid; } else if (nums[mid] == target) { right = mid; //[2,2) } } if (left == nums.length) return -1; // 没有找到 return nums[left] == target? right: -1; // 这两个语句的顺序不能乱 否则数组越界 } // 当数组中有重复元素,寻找右边界 public int search_3(int[] nums, int target) { if (nums == null || nums.length == 0) return -1; int left = 0, right = nums.length; // 左闭右开[left, right) while(left < right) { // [left, left) [2,3) int mid = left + ((right - left) >> 1); // 向下取整 if (nums[mid] < target) { left = mid + 1; } else if (nums[mid] > target) { right = mid; } else if (nums[mid] == target) { left = mid + 1; // [2,3) } } if (right == 0) return -1; return nums[right-1] == target? left-1: -1; } }
作者:Ryanjie
出处:http://www.cnblogs.com/ryanjan/
本文版权归作者和博客园所有,欢迎转载。转载请在留言板处留言给我,且在文章标明原文链接,谢谢!
如果您觉得本篇博文对您有所收获,觉得我还算用心,请点击右下角的 [推荐],谢谢!