【问题描述】
给定两个数组a、b,采用二分法找出这两个有序线性序列第 i 小的元素。(前提:i 一定小于两个数组长度之和)
【解题思路】
因为题目要求使用二分法来实现这道题,所以我们采用二分法,用递归实现查找过程,分析过程如下:1、因为用二分法,所以首先先取有序数组a中间数的下标 amiddle,有序数组b中间数的下标bmiddle;
2、分出来后要分析可能会出现的三种情况:
第一种:amiddle前面的数字个数加上bmiddle前面的数字个数大于 i-1:
继续比较a[amiddle]与b[bmiddle]的大小:
(1)如果a[amiddle] >= b[bmiddle],则第 i 小的数不会出现在amiddle以后的数中,可以排除掉amiddle以后的数字;
(2)如果a[amiddle] < b[bmiddle],则第 i 小的数不会出现在bmiddle以后的数中,可以排除掉bmiddle以后的数字;
第二种:amiddle前面的数字个数加上bmiddle前面的数字个数小于 i-1:
继续比较a[amiddle]与b[bmiddle]的大小:
(1)如果a[amiddle] >= b[bmiddle],则第 i 小的数不会出现在amiddle前面的数中,可以排除掉amiddle前面的数字;
(2)如果a[amiddle] < b[bmiddle],则第 i 小的数不会出现在bmiddle前面的数中,可以排除掉bmiddle前面的数字;
第三种:amiddle前面的数字个数加上bmiddle前面的数字个数等于 i-1,说明第 i 小的数不是a[amiddle]就是b[bmiddle],进一步比较a[amiddle]与b[bmiddle]的大小:
(1)如果a[amiddle] < b[bmiddle],则第 i 小的数就是a[amiddle],返回a[amiddle;]
(2)如果a[amiddle] >= b[bmiddle],则第 i 小的数就是b[middle],返回b[bmiddle];
3、递归结束则可以找出第 i 小的数了
【实现代码】
import java.util.Scanner;
public class binarySearch {
public static void main(String []args) {
int a[]= {10,15,21,22,36,38};
int b[]= {2,3,8,16,24,27,38,40};
Scanner re=new Scanner(System.in);
System.out.print("请输入要查询的第k小的数:k=");
int k=re.nextInt();
int result=findResult(a, b, k);
System.out.println(result);
re.close();
}
private static int findResult(int a[],int b[],int k) {
int aright=a.length,bright=b.length;
if(k==1)
return a[0]<b[0]?a[0]:b[0];
else if(k==aright+bright)
return a[aright-1]>b[bright-1]?a[aright-1]:b[bright-1];
else
return search(a,b,0,a.length-1,0,b.length-1,k);
}
private static int search(int[] a, int[] b,int aleft,int aright,int bleft,int bright, int k) {
int amiddle=(aleft+aright)/2;
int bmiddle=(bleft+bright)/2;
if(amiddle+bmiddle<k-1) {
if(a[amiddle]>b[bmiddle])
return search(a,b,aleft,aright,bmiddle+1,bright,k);
else
return search(a,b,amiddle+1,aright,bleft,bright,k);
}
else if(amiddle+bmiddle==k-1) {
if(a[amiddle]>b[bmiddle])
return b[bmiddle];
else
return a[amiddle];
}
else{
if(a[amiddle]>b[bmiddle])
return search(a,b,aleft,amiddle-1,bleft,bright,k);
else
return search(a,b,aleft,aright,bleft,bmiddle-1,k);
}
}
}