Google Interview Question

There are n integers in disk. Memory has m space. how to sort the data efficiently.

Interview Answers

Anonymous

Jul 14, 2014

This can be done in O(d*n) where d is the maximal number of digits of the integers using radix sort. void SortIntArray(int* source, int length, int nDigits, int*dst) { int* tmp = new int[length]; int occurences[11]; int kthDigit; int factor = 1; for (int j = 0; j < length; ++j) { tmp[j] = source[j]; } for (int k = 0; k < nDigits; ++k) { for (int j = 0; j < 11; ++j) { occurences[j] = 0; } for (int j = 0; j < length; ++j) { kthDigit = (tmp[j] / factor) % 10; occurences[kthDigit + 1]++; } int cumSum = 0; for (int j = 0; j < 10; ++j) { occurences[j + 1] += occurences[j]; } for (int j = 0; j < length; ++j) { kthDigit = (tmp[j] / factor) % 10; dst[occurences[kthDigit]++] = tmp[j]; } for (int j = 0; j < length; ++j) { tmp[j] = dst[j]; } factor *= 10; } delete[] tmp; return; }

1

Anonymous

Mar 24, 2015

It sounds like they are asking for an external merge sort Something like this, exceptI've done it for bytes not integers public class ExternalMergeSort { int MemoryLimit = 100; public void Sort(string filename, string newFilename) { List fileChunks = SplitFile(filename, MemoryLimit); SortChunks(fileChunks); Merge(fileChunks, newFilename, MemoryLimit); } public List SplitFile(string filename, int memoryLimit) { var filenames = new List(); string outFilename; FileStream outStream = GetNewChunkStream(memoryLimit / 2, out outFilename); filenames.Add(outFilename); using (FileStream inStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, memoryLimit / 2)) { int value = inStream.ReadByte(); while (value >= 0) { outStream.WriteByte((byte)value); value = inStream.ReadByte(); if (value >= 0 && outStream.Length > memoryLimit) { outStream.Close(); outStream = GetNewChunkStream(memoryLimit / 2, out filename); filenames.Add(filename); } } outStream.Close(); return filenames; } } private FileStream GetNewChunkStream(int bufferSize, out string filename) { filename = Path.GetTempFileName(); return new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Write, bufferSize); } private void SortChunks(List filenames) { foreach (string filename in filenames) { byte[] bytes = File.ReadAllBytes(filename); Array.Sort(bytes); File.WriteAllBytes(filename, bytes); } } private void Merge(List fileChunks, string outputFile, int memoryLimit) { var queue = new PriorityQueue(); // put 1 byte in for each stream int bufferSize = memoryLimit / (fileChunks.Count + 1); foreach (string filename in fileChunks) { var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize); int value = stream.ReadByte(); if (value >= 0) queue.Enqueue((byte)value, stream); } using (var outStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.Write, bufferSize)) { while (!queue.IsEmpty()) { HeapNode current = queue.Dequeue(); outStream.WriteByte(current.Priority); // read next byte FileStream stream = current.Value; int value = stream.ReadByte(); if (value >= 0) queue.Enqueue((byte)value, stream); } } } }

1

Anonymous

Feb 22, 2014

I did it O(n^2) but there is a faster solution.