海量数据处理面试题
有2.5E个整数数据,找出其中重复的,给定的内存是600M。
由于题目描述的不够清晰,现在假定整数指的是int32,其中有正有负有零,范围就是int32的范围。
可以用编程珠玑里的位图来处理,由于内存只有600M,刚好可以将数据分作正,负和0来处理,这个范围是两个2^31,那就是一次处理位图占用512M的内存。
之前我用byte数组表示位图,有很多繁琐的步骤和数据结构,在分析博客园其他大牛的文章和手头资料之后决定使用BitArray来处理。
总共需要两个位图,一个标志出现过的整数,一个标志这个整数是重复出现的。
程序分作数据生成和处理两个部分。处理数据的时候程序大概占用了500多M。时间用的还蛮多的,占用的CPU时钟数如下:
代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace 生成数据
{
class Program
{
static void Main(string[] args)
{
//GenerateData();
long time = DateTime.Now.Ticks;
ProcessData();
time = DateTime.Now.Ticks - time;
Console.WriteLine("处理数据所花费的时间为{0}", time);
Console.ReadKey();
}
private static void ProcessData()
{
int max = int.MaxValue;
int min = int.MinValue;
BitArray existFlag = new BitArray(max);
BitArray countFlag = new BitArray(max);
byte zeroFlags = 0, minFlags = 0;
using (FileStream data = new FileStream("data", FileMode.OpenOrCreate))
{
int length = (int)(data.Length / sizeof(int)), temp;
var br = new BinaryReader(data);
for (int i = 0; i < length; i++)
{
temp = br.ReadInt32();
if (temp > 0)
{
if (existFlag.Get(temp) == false)
{
existFlag.Set(temp, true);
}
else
{
if (countFlag.Get(temp) == false)
{
countFlag.Set(temp, true);
}
}
}
}
FileStream result = new FileStream("result(大于0).txt", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(result);
for (int i = 0; i < int.MaxValue; i++)
{
if (countFlag.Get(i) == true)
{
sw.Write(i.ToString());
sw.Write(" ");
}
}
existFlag.SetAll(false);
countFlag.SetAll(false);
//现在开始处理负数和0
data.Position = 0;
for (int i = 0; i < length; i++)
{
temp = br.ReadInt32();
if (temp < 0 && temp > min)
{
if (existFlag.Get(Math.Abs(temp)) == false)
{
existFlag.Set(Math.Abs(temp), true);
}
else
{
if (countFlag.Get(Math.Abs(temp)) == false)
{
countFlag.Set(Math.Abs(temp), true);
}
}
}
else if (temp == 0)
{
zeroFlags++;
}
else if (temp == min)
{
minFlags++;
}
}
result = new FileStream("result(小于等于0).txt", FileMode.OpenOrCreate);
sw = new StreamWriter(result);
if (zeroFlags > 1)
{
sw.Write("0 ");
}
for (int i = 0; i < int.MaxValue; i++)
{
if (countFlag.Get(i) == true)
{
sw.Write((-i).ToString());
sw.Write(" ");
}
}
if (minFlags > 1)
{
sw.Write(min);
}
}
}
private static void GenerateData()
{
using (FileStream data = new FileStream("data", FileMode.OpenOrCreate))
{
int n = 250000000;
Random random = new Random();
BinaryWriter bw = new BinaryWriter(data);
int max = int.MaxValue;
int min = int.MinValue;
for (int i = 0; i < n; i++)
{
bw.Write(random.Next(random.Next(min, 0), random.Next(0, max)));
}
}
}
}
}
输出结果分为大于0和小于等于0的。
结束。