27.10.2014 Views

Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions

Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions

Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Solutions</strong> to Chapter 11 | System Design <strong>and</strong> Memory Limits<br />

Follow Up: What if we have only 10 MB memory?<br />

It’s possible to find a missing integer with just two passes of <strong>the</strong> data set. We can divide up<br />

<strong>the</strong> integers into blocks of some size (we’ll discuss how to decide on a size later). Let’s just assume<br />

that we divide up <strong>the</strong> integers into blocks of 1000. So, block 0 represents <strong>the</strong> numbers<br />

0 through 999, block 1 represents blocks 1000 - 1999, etc. Since <strong>the</strong> range of ints is finite, we<br />

know that <strong>the</strong> number of blocks needed is finite.<br />

In <strong>the</strong> first pass, we count how many ints are in each block. That is, if we see 552, we know<br />

that that is in block 0, we increment counter[0]. If we see 1425, we know that that is in block<br />

1, so we increment counter[1].<br />

At <strong>the</strong> end of <strong>the</strong> first pass, we’ll be able to quickly spot a block that is missing a number. If<br />

our block size is 1000, <strong>the</strong>n any block which has fewer than 1000 numbers must be missing a<br />

number. Pick any one of those blocks.<br />

In <strong>the</strong> second pass, we’ll actually look for which number is missing. We can do this by creating<br />

a simple bit vector of size 1000. We iterate through <strong>the</strong> file, <strong>and</strong> for each number that<br />

should be in our block, we set <strong>the</strong> appropriate bit in <strong>the</strong> bit vector. By <strong>the</strong> end, we’ll know<br />

which number (or numbers) is missing.<br />

Now we just have to decide what <strong>the</strong> block size is.<br />

A quick answer is 2^20 values per block. We will need an array with 2^12 block counters <strong>and</strong><br />

a bit vector in 2^17 bytes. Both of <strong>the</strong>se can comfortably fit in 10*2^20 bytes.<br />

What’s <strong>the</strong> smallest footprint? When <strong>the</strong> array of block counters occupies <strong>the</strong> same memory<br />

as <strong>the</strong> bit vector. Let N = 2^32.<br />

counters (bytes): blocks * 4<br />

bit vector (bytes): (N / blocks) / 8<br />

blocks * 4 = (N / blocks) / 8<br />

blocks^2 = N / 32<br />

blocks = sqrt(N/2)/4<br />

It’s possible to find a missing integer with just under 65KB (or, more exactly, sqrt(2)*2^15<br />

bytes).<br />

1 int bitsize = 1048576; // 2^20 bits (2^17 bytes)<br />

2 int blockNum = 4096; // 2^12<br />

3 byte[] bitfield = new byte[bitsize/8];<br />

4 int[] blocks = new int[blockNum];<br />

5<br />

6 void findOpenNumber() throws FileNotFoundException {<br />

7 int starting = -1;<br />

8 Scanner in = new Scanner (new FileReader (“input_file_q11_4.txt”));<br />

2 0 3<br />

<strong>Cracking</strong> <strong>the</strong> <strong>Coding</strong> <strong>Interview</strong> | Concepts <strong>and</strong> Algorithms

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!