摘自: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
所以可以进一步把二分搜索的数组优化,减少所需要搜索的数值的个数。