增加难度的抽签问题(最内两层使用二分法)

摘自:http://pan.baidu.com/share/link?shareid=3236456167&uk=1946291292

上篇文章中的方法,可以继续优化!思路:让我们着眼于内侧的两个循环。

检查是否有c和d使得k[c] + k[d] = m - k[a] -  k[b]

这种情况并不能直接使用二分搜索。但是,如果预先枚举出k[c]+k[d]所得的n*n个数字并排好序,便可以利用二分索了。


代码实现:

#include <stdio.h>

#define MAX_N 100


//冒泡排序发
static void sort(int n, int arry[]);


//生成组合的数组
static void make_addarry(int n, int f[], int t[]);


/*
*二分查找法
*s:查找的目标值
*size:数组的大小
*a:查找的数组,这个数组是从小到打排序的
*/
static int search(int s, int size, int a[]);


int main(int argc, char** argv)
{

int arry[MAX_N];
int n;
int m;

//数组组合之后的新数组
int addarry[MAX_N*MAX_N];


printf( "input your m:" );
scanf("%d", &m);
printf( "input your n:" );
scanf("%d", &n);
printf( "init your array\n" );
int i = 0;
for(i=0;i<n;i++)
{
scanf("%d", &arry[i]);
}


for(i=0;i<n;i++)
{
printf("arry[%d]=%d ", i, arry[i]);
}


printf( "\n" );


make_addarry(n, arry, addarry);


sort(n*n, addarry);


printf("排序之后的数组");
for(i=0;i<n*n;i++)
{
printf("arry[%d]=%d ", i, addarry[i]);
}
printf( "\n" );



int j = 0;
//4次抽签
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
//二分查找法,从addarry查找是否存在find_t
int  find_t = m - arry[i] - arry[j];

if(0 == search(find_t, n*n, addarry))
{
printf( "Maybe you can win\n" );
return 0;
}

  }
}


printf( "you can not win\n" );




return 0;
}




//冒泡排序发
static void sort(int n, int arry[])
{
int i = 0;
int j = 0;
int m = n;
for(i=0;i<n-1;i++)
{
//m = m - 1;
for(j=0;j<n-i-1;j++)
{
if(arry[j] > arry[j+1])
{
int temp = arry[j];
arry[j] = arry[j+1];
arry[j+1] = temp;
}
}

}


}


static void make_addarry(int n, int f[], int t[])
{
int i = 0;
int j = 0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
t[i*n+j] = f[i] + f[j];
}
}

for(i=0;i<n*n;i++)
{
printf("arry[%d]=%d ", i, t[i]);
}

}


static int search(int s, int size, int a[])
{
int l = 0;
int r = size;

while(r-l >= 1)
{
int i = (l+r)/2;


if(s == a[i])//直接找到了这个值
{
return 0;
}
else if(s > a[i])//s在a[i]的右边
{
l = i + 1;
}
else//s在的a[i]左边
{
r = i;
}


}


return -1;
}

--------------------------------------------------------------------------------------------

后记 :组合数组的问题

数组 arry[n] 两次抽签可组合为数组addarry[n*n],这个数组中有(n-1)+(n-2)+...+1个数值是重复的,即(n-1)(n-1+1)/2

如果将addarry[n*n]数组中的重复数值去掉,那么需要二分法搜索的数组大小为:

n*n - n(n-1)/2  即n(n+1)/2

所以可以进一步把二分搜索的数组优化,减少所需要搜索的数值的个数。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值