面试题之陈利人 两个数组中求第k小元素

69 篇文章 0 订阅
60 篇文章 3 订阅

两个数组中求第k小数

  • 真言

幸福的人生是不存在的,什么叫幸福?不完美的完美就是幸福。

  • 引言

陈利人先生的题目很有思考性,很喜欢。

  • 题目

给两个同样长度排好序的数组,找出第k个最小的数。

  • 思路

思路很清晰,借鉴与折半查找,不断减小查找范围。

举个例子吧,两个数组(a and b)如下(一共16个数),看看我们是怎么减小搜索范围的,我们找出第九小的数


第九小的数肯定在两个数组的前九个里,但是每个数组就八个数,所以没有减小范围。然后找出数组a的中间数,如下


再在数组b里折半查找这个数,如下


发现不存在,则返回最靠近查找数的数,如上。然后这时候我们发现这两个数以及其前面的数一共是5个,所以第六小数肯定不在刚才那个范围里,则缩小范围


缩小后,得到的范围如下,则查找第(6-5)小数,即第一小数,这时候就特简单了。



  • 实验

  • 代码

    test.cpp
    #include<iostream>
    using namespace std;
    
    // define size for array
    const int size = 20;
    
    // function declare to the problem
    int Super_bisearch(int * A,const int Asize,int * B,const int Bsize,const int k);
    // function declare to binary search
    int Bisearch(int *d,int length,int key );
    
    // function main
    int main()
    {
    
    	int * A = new int[size];
    	int * B = new int[size];
    	for(int i = 0;i<size;i++)
    	{
    		A[i] = 2*i;
    		cout<<A[i]<<" ";
    		B[i] = 2*i+5;
    		cout<<B[i]<<" ";
    	}
    	cout<<endl;
    	int i = 1;
    	while( i <= size*2 )
    	{
    		cout<<"第 "<<i<<" 小元素为  "<<Super_bisearch(A,size,B,size,i)<<endl;
    		i++;
    	}
    	
    	system("pause");
    	return 0;
    }
    
    // function define to the problem
    int Super_bisearch(int * A,const int Asize,int * B,const int Bsize,const int k)
    {
    	if(A == NULL || B == NULL || Asize < 0 || Bsize <0 || k <= 0 || k > (Asize+Bsize))
    	{
    		cout<<"exception of input super_bisearch"<<endl;
    		return 1;
    	}
    	else if(Asize != Bsize)
    	{
    		cout<<"Asize != Bsize"<<endl;
    		return 1;
    	}
    	
    	int sa,sb,ba,bb;
    	sa = 0;
    	sb = 0;
    	ba = (Asize < k)? Asize:k;
    	bb = (Bsize < k)? Bsize:k;
    	ba--;bb--;
    	int ca ;
    	int cb ;
    	int number = k;
    	ca = (sa+ba)/2;
    	cb = Bisearch(B,Bsize,A[ca]);
    	while( number > 2 &&(sa<ca || sb<cb))
    	{
    		ca = (sa+ba)/2;
    		cb = Bisearch(B,Bsize,A[ca]);
    		if( number > ( ca + cb - sa - sb) )
    		{
    			number = number - ( ca + cb - sa - sb );
    			sa = ca;
    			sb = cb;	
    			if( ( ca + cb - sa - sb ) == 0) break;
    		}
    		else if( ( ca + cb - sa - sb) == number )
    		{
    			return A[ca]>B[cb]?A[ca]:B[cb];
    		}
    		else if( number < ( ca + cb - sa - sb) )
    		{
    			ba = ca;
    			bb = cb;
    		}
    	}
    	int * d = new int[ba-sa+1+bb-sb+1];
    	int i = sa,j = sb,bit = 0;
    	while(i <= ba && j <= bb)
    	{
    		if(A[i]<B[j])
    			d[bit++] = A[i++];
    		else d[bit++] = B[j++];
    	}
    	while(i<=ba)
    		d[bit++] = A[i++];
    	while(j<=bb)
    		d[bit++] = B[j++];
    	return d[number-1];
    
    }
    
    // function define to binary search
    int Bisearch(int *d,int length,int key )
    {
    	if( d == NULL && length <= 0 )
    	{
    		cout<<"exception of input Bisearch"<<endl;
    		return -1;
    	}
    	else{
    		int s = 0 ;
    		int e = length-1 ;
    		int c ; 
    		while(s < e)
    		{
    			c = ( s + e ) / 2;
    			if( d[c] == key )
    			{
    				return c;
    			}
    			else if( key < d[c] )
    			{
    				e = c-1;
    			}
    			else if( key > d[c] )
    			{
    				s = c;
    				if( e-s == 1 && d[s]<d[e])
    				{
    					return s;
    				}
    			}
    		}
    		return s;
    	}
    }


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值