Write a method to shuffle a deck of cards. It must be a perfect shuffle – in other words, each 52! permutations of the deck has to be equally likely. Assume that you are given a random number generator which is perfect.

My initial thoughts:
We first select a card randomly from the 52 cards. That is probability of 1/52. We then select another card from the rest 51 cards. That is probability of 1/51. So on and so forth. Finally we have a particular permutation with probability of 1/52!, which is expected.

Solution:
Let’s start with a brute force approach: we could randomly selecting items and put them into a new array. We must make sure that we don’t pick the same item twice though by somehow marking the node as dead.

By doing it this way, it’s much easier for the algorithm to “know”” that the first k elements are dead than that the third, fourth, nineth, etc elements are dead. We can also optimize this by merging the shuffled array and the original array:

Write a function that adds two numbers You should not use + or any arithmetic operators.

My initial thoughts:
We should take care of two things: adding and carry. Addition can be done using XOR(^). Carry can be done using AND(&). The only tricky part is that when we have two bits like 1 and 0 but then we have carry from previous position, then 1 & 0 = 0 suggests no carry but actually 1 + 0 + 1 will produce a carry. So we branch into two case: 1 + 1 will definitely produce a carry no matter what; 1 + 0 + 1 will produce new carry.

Solution:
To investigate this problem, let’s start off by gaining a deeper understanding of how we add numbers. We’ll work in Base 10 so that it’s easier to see. To add 759 + 674, we would usually add digit[0] from each number, carry the one, add digit[1] from each number, carry the one, etc. You could take the same approach in binary: add each digit, and carry the one as necessary.
Can we make this a little easier? Yes! Imagine we decided to split apart the “addition” and “carry” steps. That is, we do the following:

Add 759 + 674, but “forget” to carry we then get 323

Add 759 + 674 but only do the carrying, rather than the addition of each digit. We then get 1110

Add the result of the first two operations (recursively, using the same process de- scribed in step 1 and 2): 1110 + 323 = 1433

Now, how would we do this in binary?

If we add two binary numbers together but forget to carry, bit[i] will be 0 if bit[i] in a and b are both 0 or both 1. This is an XOR

If we add two numbers together but only carry, we will have a 1 in bit[i] if bit[i-1] in a and b are both 1’s. This is an AND, shifted

Design an algorithm to find all pairs of integers within an array which sum to a specified value.

My initial thoughts:
For each element in the array, we can find its complement in the array and output this pair. To speed up the search, we can use binary search. Therefore we need to sort the array first, . Then for each element, we search for its complement, that’s another . Together it’s still .

Write a method to generate a random number between 1 and 7, given a method that generates a random number between 1 and 5. (i.e., implement rand7() using rand5()).

Solution:
First, observe that we cannot do this in a guaranteed finite amount of time. Why? Let’s see by a parallel example: How would you use rand2() to create rand3()?
Observe that each call of rand2() and the corresponding decision you make can be represented by a decision tree. On each node, you have two branches. You take the left one when rand2() equals 0 (which happens with 1/2 probability). You take the right one when rand2() equals 1 (which happens with 1/2 probability). You continue branching left and right as you continue to call rand2(). When you reach a leaf, you return a result of 1, 2 or 3 (your rand3() results).

What’s the probability of taking each branch? 1/2

What’s the probability to reach a particular leaf node? 1/2^j (for some j).

What the probability of returning 3 (for example)? We could compute this by summing up the probabilities of reaching each leaf node with value 3. Each of these paths has probability 1/2^j, so we know that the total probability of returning 3 must be a series of terms of reciprocal powers of 2 (e g , 1/2^x + 1/2^y + 1/2^z + …).

We also know, however, that the probability of returning 3 must be 1/3 (because rand3() should be perfectly random). Can you find a series of reciprocal powers of 2 that sum to 1/3? No, because 3 and 2 are relatively prime.
We can similarly conclude that to solve this problem, we will need to accept a small (infinitesimally small) chance that this process will repeat forever. That’s ok.
So, how do we solve this?
In order to generate a random number between 1 and 7, we just need to uniformly generate a larger range than we are looking for and then repeatedly sample until we get a number that is good for us. We will generate a base 5 number with two places with two calls to the rand5().

How does it work? Think of it like this: imagine printing out this double-dimension array on paper, tacking it up to a dart board and randomly throwing darts at it. If you hit a non-zero value, it’s a statistically random value between 1 and 7, since there are an equal number of non-zero values to choose from. If you hit a zero, just keep throwing the dart until you hit a non-zero. That’s what this code is doing: the i and j indexes randomly select a location on the dart board, and if we don’t get a good result, we keep throwing darts.

Since XML is very verbose, you are given a way of encoding it where each tag gets mapped to a pre-defined integer value The language/grammar is as follows:
Element –> Element Attr* END Element END [aka, encode the element tag, then its attributes, then tack on an END character, then encode its children, then another end tag]
Attr –> Tag Value [assume all values are strings] END –> 01
Tag –> some predefined mapping to int
Value –> string value END
Write code to print the encoded version of an xml element (passed in as string).
FOLLOW UP
Is there anything else you could do to (in many cases) compress this even further?

Design a method to find the frequency of occurrences of any given word in a book.

My initial thoughts:
Assume this query would be asked for multiple times. Otherwise, if it’s a one-time thing, we can do no better than scanning through the book. We then need to build a Trie with nodes as character along with its count. When asked for particular word, we search through the tree.

You are given an array of integers (both positive and negative). Find the continuous sequence with the largest sum. Return the sum.
EXAMPLE
Input: {2, -8, 3, -2, 4, -10}
Output: 5 (i.e., {3, -2, 4})

My initial thoughts:
We need to track two variables: max sum ending at position i and max sum so far. We update maxSumEndHere to zero if adding the current element will make the sum be negative, otherwise we keep track of the maximum sum. We update maxSumSoFar according to maxSumEndHere. We then return maxSumSoFar.My initial code: