@陈利人 : #面试题#给定两个数组X和Y,元素都是正数。请找出满足如下条件的数对的数目: x^y > y^x,即x的y次方>y的x次方;x来自X数组,y来自Y数组

数对数目分析
原题

给定两个数组X和Y,元素都是正数。请找出满足如下条件的数对的数目:

  1. x^y > y^x,即x的y次方>y的x次方

  2. x来自X数组,y来自Y数组

分析

假设数组X的长度为m,数组Y的长度为n,最直接的暴力法,时间复杂度为O(m*n),但这样的话,并不需要都是正数这个条件的。那么,我们该如何优化呢?

x^y>y^x,对于x和y来讲,有什么规律呢?该如何发现呢?这里其实有规律的,大多数的条件下,当y>x的时 候,x^y>y^x,但是有一些例外,1,2,3,4几个数,需要特殊的考虑,比如2^4=4^2。这个大家可以通过在纸上写写画画来得到,相对繁 琐,我们就不进一步分析了。

我们可否对于原式做一些数学变换呢?使得式子变化简单。如何去做呢?这个式子的复杂体现在两边都是指数的形式,如何变化一下呢?我们很自然的就想 到,逆运算对数运算,则,两边取对数可得:ylog(x)>xlog(y)。这里同学们可能要问,可以直接取对数么?取对数之后,大小关系仍旧满足 么?这里是有两点保证的:

  1. 对数函数的性质,单调递增

  2. 题目中的说明:元素都是正数

对于式子:ylog(x)>xlog(y),x和y都是正数,则进一步有:两边同时除以xy,则:log(x)/x >log(y)/y。这个式子,看起来也复杂,但是,x和y都在各自的一边,要简单的多。

对于log(x)/x >log(y)/y,

  1. 数组X和Y分别计算log(x)/x,log(y)/y

  2. 然后对Y进行排序O(nlogn)

  3. 遍历X数组,对于每一个x,在Y中,进行二分查找,即可。

总的时间复杂度为O(nlogn + mlogn).


程序结果图片





code 


// test_01.cpp : Defines the entry point for the console application.
//

#include<stdio.h>
#include<stdlib.h> 

int main()
{
	int half(int m,int n,int x,int y);
	int x,y,result;


	printf("请输入正整数 x,y \n");
	scanf("%d",&x);
	scanf("%d",&y);
	result=half(1,2,x,y);
	printf("商=%d \n",result) ;
	system("pause");
	return 0;
}


// 类似折半查找商值:running time(log n)
/* functiong check()
input(m,n,x,y)
out result

if( m <=result<=n )
   折半查找就ok
else return half( n+1,2*n+2 ,x,y )
*/
int half(int m,int n,int x,int y)
{
	int check(int x,int y, int d);

	if(check(x,y,m)==0 )
	{
		return m ;
	}
	else if( check(x,y,n)==0 )
	{
		return n;
	}
    else if( check(x,y,n) == -1 )
	{
		if( check(x,y,(n+m)/2) == 0 )
			return (n+m)/2;
		else if( check(x,y,(n+m)/2) == 1 )
			return half( (n+m)/2+1,n-1,x,y );
		else if( check(x,y,(n+m)/2) == -1 )
			return half( m+1,(n+m)/2-1,x,y );
	}
    else return half( n+1,2*n+2,x,y );

}


// check the relation of the right result and d :running time(1)
/* functiong check()
input(x,y,d)
if( d==result )
   return 0;
else if( d>result )
   return -1;
else return 1;
*/

int check(int x,int y, int d)
{
	printf( "x = %d, y = %d,d = %d\n",x,y,d );
	if( x-d*y<y && x-d*y>=0 )
	{		
		return 0 ;
	}
	else if( x-d*y>=y )
	{
		return 1;
	}
	else if( x-d*y< 0 )
	{
		return -1;
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值