二分查找
@Test public void testBinSearch() { int[] i = {1, 3, 5, 6, 8}; int[] r1 = {bS1(i, 0), bS1(i, 1), bS1(i, 3), bS1(i, 6), bS1(i, 8), bS1(i, 9)}; System.out.println(Arrays.toString(r1)); System.out.println("--------------------"); int[] r2 = {bS2(i, 0), bS2(i, 1), bS2(i, 3), bS2(i, 6), bS2(i, 8), bS2(i, 9)}; System.out.println(Arrays.toString(r2)); System.out.println("--------------------"); int[] r3 = {bS3(i, 0), bS3(i, 1), bS3(i, 3), bS3(i, 6), bS3(i, 8), bS3(i, 9)}; System.out.println(Arrays.toString(r3)); System.out.println("--------------------"); int[] r4 = {bS4(i, 0), bS4(i, 1), bS4(i, 3), bS4(i, 6), bS4(i, 8), bS4(i, 9)}; System.out.println(Arrays.toString(r4)); } public int bS1(int[] nums, int target) { int left = 0; int right = nums.length - 1; // 终止条件[right + 1, right],此时搜索区间为空 while (left <= right) { int mid = left + ((right - left) >> 1); if (nums[mid] == target) return mid; if (nums[mid] < target) left = mid + 1; if (nums[mid] > target) right = mid - 1; } return -1; } public int bS2(int[] nums, int target) { int left = 0; int right = nums.length; // 右边界初始为length,取不到 // 终止条件[right, right],此时搜索区间非空,但右边界不可能为target while (left < right) { int mid = left + ((right - left) >> 1); if (nums[mid] == target) return mid; if (nums[mid] < target) left = mid + 1; if (nums[mid] > target) right = mid; // right边界永远不可能为target,不需要对结果打补丁 } return -1; } public int bS3(int[] nums, int target) { int left = 0; int right = nums.length - 1; // 右边界初始为最后一个元素 // 终止条件[right, right],此时搜索区间非空,且右边界可能为target,需要对单独最后一个元素进行判断 while (left < right) { int mid = left + ((right - left) >> 1); if (nums[mid] == target) return mid; if (nums[mid] < target) left = mid + 1; if (nums[mid] > target) right = mid - 1; // right边界有可能为target,需要对结果打补丁 } return nums[left] == target ? left : -1; } public int bS4(int[] nums, int target) { int left = 0; int right = nums.length; // 右边界初始为length,有可能有边界从始至终都没有变化,需要单独处理 // 终止条件[right, right],此时搜索区间非空,且右边界可能为target,需要对单独最后一个元素进行判断 while (left < right) { int mid = left + ((right - left) >> 1); if (nums[mid] == target) return mid; if (nums[mid] < target) left = mid + 1; if (nums[mid] > target) right = mid - 1; // right边界有可能为target,需要对结果打补丁 } if (right == nums.length) return -1; return nums[left] == target ? left : -1; } @Test public void testBinSearchPlus() { int[] nums = {1, 2, 2, 2, 3}; int[] r1 = {bSL(nums, 0), bSL(nums, 1), bSL(nums, 2), bSL(nums, 3), bSL(nums, 4)}; System.out.println(Arrays.toString(r1)); System.out.println("-----------------"); int[] r2 = {bSR(nums, 0), bSR(nums, 1), bSR(nums, 2), bSR(nums, 3), bSR(nums, 4)}; System.out.println(Arrays.toString(r2)); } // 最左侧的target public int bSL(int[] nums, int target) { int left = 0; int right = nums.length; while (left < right) { // 结束条件left == right int mid = left + ((right - left) >> 1); if (nums[mid] >= target) right = mid; // 右边界可能为target if (nums[mid] < target) left = mid + 1; // 左边界依次逼近右边界 } if (left == nums.length) return -1; return nums[left] == target ? left : -1; } // 最右侧的target public int bSR(int[] nums, int target) { int left = 0; int right = nums.length; while (left < right) { int mid = left + ((right - left) >> 1); if (nums[mid] <= target) left = mid + 1; // 左边界的左侧可能为target if (nums[mid] > target) right = mid; } if (left == 0) return -1; return nums[left - 1] == target ? left - 1 : -1; }