| 发表于:2007-10-16 16:47:5318楼 得分:0 |
参考这个题目,据说是微软出的: 有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数。 研究了好几天,写出来一个看起来象o(n)的算法,o(nlog)就不用写了. - c# code
using system;
namespace minabs
{
class program
{
static void main(string[] args)
{
int n = 100;
int[] a = new int[n];
random rand = new random();
int min = int.maxvalue;
int max = int.minvalue;
console.writeline("产生了" + n + "个数据的实验数组,");
for (int i = 0; i < n; i++)
{
//赋值并且取到最大最小值
//a[i] = rand.next(int.minvalue, int.maxvalue);
a[i] = rand.next(-100, 100);
if (a[i] < min) { min = a[i]; }
if (a[i] > max) { max = a[i]; }
console.write(a[i] + " ");
}
console.writeline();
console.writeline("在o(n)内得到最大最小分别是:");
console.writeline(max + "和" + min);
long offset = (long)max + math.abs((long)min);
//规划数组的长度。每个byte有8位长
int len = (int)(offset >> 3) +1 ;
byte[] b = new byte[len];
int kkkk = 0;
bool issame = false;//是否有重合点标记
//o(n)的时间内分配到了byte[]中。
for (int i = 0; i < n; i++)
{
offset = (long)a[i] - (long)min;
int index = (int)(offset >> 3);
int temp = b[index];
//把末k位变成1
//把右数第k位变成1 例如:(00101001->00101101,k=3) x | (1 << (k-1))
int tempoffset = (1 << ( (int)(offset & 7) ) );
//判断重合
if (!issame)
{
kkkk = temp & tempoffset;
if ((temp & tempoffset) >= 1)
{
issame = true;
//如果0算最小距离就在这里退出吧。本代码判断重合,但没把0作为结果。
}
}
int bbb = b[index];
b[index] |= (byte)(tempoffset);
int aaa = b[index];
}
//最小距离初始为最大。
console.writeline("在o(n)的时间内分配到了byte[]中,正在计算最小距离,请稍候。。。。。");
long minabs = long.maxvalue;
long lastindex = -1;
//在常数范围内循环,复杂度不增加。最坏的情况是32*int.maxvalue次。
for (int i = 0; i < b.length; i++)
{
//if (b[i] == 0) { continue; }
//在常数范围内循环,复杂度不增加。
for (int k = 0; k < 8; k++)
{
if (((b[i] >> k) & 1) == 1)
{
if (lastindex >= 0)
{
long temp = ((long)i << 3) + k - lastindex;
if (temp < minabs)
{
minabs = temp;
console.writeline("目前得到了最小距离:" + minabs);
}
}
lastindex = (i << 3) + k;
}
}
}
if (issame)
{ console.writeline("有重合点"); }
else
{ console.writeline("无重合点"); }
console.writeline("不考虑重合最小距离是:" + minabs);
console.writeline("总复杂度是:o(n)");
console.readline();
}
}
}
| | |
|