华为机试od社招刷题攻略-二分查找
二分查找
题目
输入不重复有序整数数组,使用空格隔开。查找特定整数,返回数组下标。不存在则返回-1。
输入描述 第1行:给定整数数组 第2行:目标值 输出: 数组下标 输入 1 2 3 4 5 6 7 8 9 6 输出 5 输入 1 2 3 4 5 6 7 8 9 10 输出 -1
Java
package $02_pythagorean;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BinarySearch {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] numStr = br.readLine().split(" ");
int target = Integer.parseInt(br.readLine());
int[] nums = new int[numStr.length];
for (int i = 0; i < numStr.length; i++) {
nums[i] = Integer.parseInt(numStr[i]);
}
int res = binarySearch(nums, target);
System.out.println(res);
}
/**
* 迭代版本
*
* @param nums
* @param target
* @return
*/
private static int binarySearch(int[] nums, int target) {
//两端都是闭区间
int left = 0;
int right = nums.length - 1;
//注意有等号,相等时判断自己
while (left <= right) {
//取重点,这样可以防止整数溢出
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
//如果相等,说明找到,直接返回
return mid;
} else if (nums[mid] > target) {
//中点值大于目标值,说明目标值只能在[left,mid-1]中出现,右边界左移。
right = mid - 1;
} else if (nums[mid] < target) {
//中点值小于目标值,说明目标值只能在[mid+1,right]中出现,左边界右移。
left = mid + 1;
}
}
//当左边界大于右边界,比如[6,5]区间.区间已无意义,说明没找到.
return -1;
}
/**
* 递归版本
*
* @param nums
* @param target
* @return
*/
private int binarySearchWithRecursive(int[] nums, int target) {
return binarySearchWithRecursive(nums, 0, nums.length - 1, target);
}
private int binarySearchWithRecursive(int[] nums, int left, int right, int target) {
//递归结束条件,当左边界大于右边界时,没有意义,返回-1
if (left > right) {
return -1;
}
//递归体:缩小边界
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
//可以直接简写为else。前两个if走完,nums[mid]<target必成立。
left = mid + 1;
}
return binarySearchWithRecursive(nums, left, right, target);
}
@Test
public void test() {
int[] nums = {
1, 2, 3, 4, 5, 6, 7, 8, 9};
int res1 = binarySearch(nums, 6);
//单元测试api.判断两个数是否相等
Assertions.assertEquals(5, res1);
int res2 = binarySearch(nums, 10);
Assertions.assertEquals(-1, res2);
int res3 = binarySearchWithRecursive(nums, 6);
Assertions.assertEquals(5, res3);
int res4 = binarySearchWithRecursive(nums, 10);
Assertions.assertEquals(-1, res4);
}
}
要点小结
- 背诵默写迭代版本的二分查找。注意两端都是闭区间时,while需要带等号。(也有左闭右开的写法,但是比较难记)
