Facebook Interview Question


Country: India




Comment hidden because of low score. Click to expand.
4
of 4 vote

Given an integer array 'a' of the length 'N' the problem can be solved as follows:
For each 'i' in 0 to N-1:
(i) generate a random number 'k' that is betweem 'i' and N-1
(ii) swap elements a[i] and a[k]

public static void shuffle(int[] a) {
	int N = a.length;

	for (int i = 0; i < N; i++) {
		int k = i + random()*(N-i)  	// random in (i, N-1)
		int aux = a[i];
		a[i] = a[k];
		a[k] = aux;
	}
}

This algorithm yields in a uniform shuffling, hence all possible permutations are equally possible.

- autoboli May 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 votes

Unfortunately this is not uniform randomness as the last values would most predictably be at the begining.

- nperez@nelsonperez.com May 07, 2015 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Correct algorithm. Though small nitpick- you actually only need to loop from 0 to < n-1, since the last element will be in the final position already.

- SK May 08, 2015 | Flag
Comment hidden because of low score. Click to expand.
Comment hidden because of low score. Click to expand.
Comment hidden because of low score. Click to expand.
0
of 0 votes

We need uniform shuffle. So probability of any element picked for swapping must be equal for all elements.

Divide 0-1 range into N intervals . [0, 1/N), [1/N, 2/N), ... [(N-1)/N, N)
The random number you draw must fall into one of the intervals, its index is the element to swap current element with

e.g. N = 25 then
intervals are [0,4), [4,8), ... [96,100)

(range normalized to 0-100 otherwise, each interval is [0,0.4), [0.4, 0.8) so on )

Then for example, when you draw random number 4,5,6 or 7 then you will swap with index 1 element with the current

- mithya May 11, 2015 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Not sure why replies are saying this is not a uniform shuffle.
Conceptually, it's the same as taking out elements from the old array one by one at random, and pushing them in a new array. Except that this is done in place, with the new array being the slice from 0..i-1 and the old array from i to N-1.

- Jack Le Hamster May 11, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

public static void shuffle(int[] a) {
		
		int n = a.length;

		for (int i = 0; i < a.length - 1; i++) {

			int randNum = (int) (Math.random() * (n - i));
			swap(randNum, n - i - 1, a);
		}

	}

	public static void swap(int e1, int e2, int[] arr) {

		int temp = arr[e1];
		arr[e1] = arr[e2];
		arr[e2] = temp; 
	}

- SK May 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public int[] shuffle(int[] array) {

       int randomIndex;
       int temp;
       for (int i = 0; i < array.length; i++) {
           randomIndex = (int) Math.floor(random()*array.length);
           temp = array[i];
           array[i] = array[randomIndex];
           array[randomIndex] = temp;
       }
       return array;
   }

- Dinkleberg May 08, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

# Cmdline Input:
# prog val1 val2 ... valN

nums = ARGV.map { |v| v.to_i }
n = nums.size

res = []
idxs = (0...n).to_a
nums.each do |num|
  i = (rand * idxs.size).floor
  res[idxs[i]] = num
  idxs.delete_at i
end

puts "Shuffled array: #{res}"

- brettstahlman May 09, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

function newRandomArray() {

var arr = [1,5,3,9,0,11];
var newArr = [];

for (var i = arr.length - 1; i >= 0; i--){
var random = Math.floor(Math.random()*arr.length);
newArr.push(arr[random]);
arr.splice(random, 1);
}

document.getElementById("out").innerHTML = newArr;
}

- Denys May 10, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

function newRandomArray() {
	
    var arr = [1,5,3,9,0,11];
    var newArr = [];
    
    for (var i = arr.length - 1; i >= 0; i--){
    	var random  = Math.floor(Math.random()*arr.length);
        newArr.push(arr[random]);
        arr.splice(random, 1);
    }
    
    document.getElementById("out").innerHTML = newArr;
}

- Denys May 10, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class RandomizeArrayProblem {

    public static int binRandom(){
        return Math.random() < 0.5 ? 0 : 1;
    }

    public static int nRandom(int n){
        int result = 0;
        while(--n >= 0)
            result += binRandom();
        return result;
    }

    public static void exch(int [] a, int i, int j){
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

    public static void shuffle(int [] a){
        for(int i = 0; i < a.length; i++)
            exch(a, i, nRandom(i));
    }

    public static void main(String[] args) {
        int [] testArray =  {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        shuffle(testArray);
        System.out.println(Arrays.toString(testArray));
    }

}

- denys.o.p May 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public static String randomArray(int[] array){
Random random = new Random();
int index ;
int swap;
for(int i = 0;i < array.length;i ++){
index = random.nextInt(array.length);
swap = array[i];
array[i] = array[index];
array[index] = swap;
}
return Arrays.toString(array);
}

- ganyiwelldone May 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public static String randomArray(int[] array){
Random random = new Random();
int index ;
int swap;
for(int i = 0;i < array.length;i ++){
index = random.nextInt(array.length);
swap = array[i];
array[i] = array[index];
array[index] = swap;
}
return Arrays.toString(array);
}

- ganyiwelldone May 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

from random import randint
n = 10
arr =[]
def gen_random(n, arr):
	num = randint(0, n-1)
	if not num in arr and num != i:
		arr.append(num)
	else:
		gen_random(n, arr)
	return num

for i in range(n):
	num = gen_random(n, arr)
	
print(arr)

- Ajay Gupta May 25, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

from random import randint
n = 10
arr =[]
def gen_random(n, arr):
num = randint(0, n-1)
if not num in arr and num != i:
arr.append(num)
else:
gen_random(n, arr)
return num

for i in range(n):
num = gen_random(n, arr)

print(arr)

- Ajay Gupta May 25, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

from random import randint
n = 10
arr =[]
def gen_random(n, arr):
	num = randint(0, n-1)
	if not num in arr and num != i:
		arr.append(num)
	else:
		gen_random(n, arr)
	return num

for i in range(n):
	num = gen_random(n, arr)
	
print(arr)

- Ajay Gupta May 25, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

int *shuffle(int* source, int N)
{
	for (int i = N-1; i > 0; i--)
	{
		int p = random()*i;
		int tmp = source[i];
		source[i] = source[p];
		source[p] = tmp;
	}
	return source;

}

- hankm2004 June 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

PHP has a really easy way to solve the problem with

usort($array, 'random');

However, I'll show a custom solution to do the same thing. Note that this code only works for indexed arrays, though upon request I can extend it to work for associative arrays.

function arrShuffle($array)
{
	
	// Prevent errors.
	if (count($array) === 1) {
		return $array;
	}
	
	$newArr = array();
	foreach ($array as $key => $value) {
		
		if ($key === 0) {
			
			$newArr[] = $value;
			continue;
			
		}
		
		if (random() === 1) {

			// Add the current value to the stack.
			$newArr[$key] = $value; 
			
		} else {
			
			// Switch the value with the last value.
			$newArr[$key] = $newArr[$key-1];
			$newArr[$key-1] = $value;
			
		}
		
	}
	
	return $newArr;
}

- Rick Mac Gillis June 28, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

static int[] shuffle(int[] A) {
	Random rand = new Random();
	int[] shuffledArray = new int[A.Length];
	Array.Copy(A, shuffledArray, A.Length);
	for (int i = 0; i < shuffledArray.Length; i++) {
		swap(ref shuffledArray[i], 
		ref shuffledArray[Convert.ToInt32(rand.NextDouble() * (shuffledArray.Length - 1))]);
	}
	return shuffledArray;
}

- Chris May 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 vote

Suppose that we have a function that return a random number belong to internal [0,1), then we can draw a fuction as fllow:

void shuffle(int A[], int n)
{
	for (int i = 0; i < n - 1; ++i)
	{
		int offset = random() * (n - i);
		swap(A[i], A[i] + offset);
	}
}

- malinbupt May 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Are you sure about this? "swap(A[i], A[i] + offset)" You have a bug in your code...

- autoboli May 07, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

offset should be between 0 and n-1. Your code is generating offset between 0 and n.

- curious May 08, 2015 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 vote

ssss

- Anonymous May 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 vote

import java.util.Arrays;
import java.util.Random;

public class RandomizeArray {
    private Random rand = new Random();

    public void randomizeArray(int[] a) {
        for(int i = 0; i < a.length; i++) {
            int index = rand.nextInt(a.length);
            swapValues(a,i, rand.nextInt(a.length));
        }
    }

    private void swapValues(int[] a, int i, int i1) {
        int temp = a[i];
        a[i] = a[i1];
        a[i1] = temp;
    }

    public static void main(String[] args) {
        RandomizeArray randomizeArray = new RandomizeArray();
        int a[] = {1,2,3,4,5};
        for (int i = 0; i < a.length; i++) {
            randomizeArray.randomizeArray(a);
            System.out.println(Arrays.toString(a));
        }

    }
}

- Anonymous May 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

The random function should return a value between 0..1

- nperez@nelsonperez.com May 07, 2015 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 vote

import java.util.Arrays;
import java.util.Random;

public class RandomizeArray {
    private Random rand = new Random();

    public void randomizeArray(int[] a) {
        for(int i = 0; i < a.length; i++) {
            int index = rand.nextInt(a.length);
            swapValues(a,i, rand.nextInt(a.length));
        }
    }

    private void swapValues(int[] a, int i, int i1) {
        int temp = a[i];
        a[i] = a[i1];
        a[i1] = temp;
    }

    public static void main(String[] args) {
        RandomizeArray randomizeArray = new RandomizeArray();
        int a[] = {1,2,3,4,5};
        for (int i = 0; i < a.length; i++) {
            randomizeArray.randomizeArray(a);
            System.out.println(Arrays.toString(a));
        }

    }
}

- dvelagap May 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 vote

I was asked that in a Starbuck interview. I came up with the normal solution of recreating the array and swaping away the values.

But the interviewer interesting enough he brough a surprising fact. He mentioned that: using the random function in a very close time frame will have clustered values as it depends this function depends on time to calculate the random value.

So for this solution I'll introduce an small delay of a 10th of a millisecond to enable the random function to be more fairly distribute.

Also I'm reusing the array as it did mention that it returns an array but not a new array.

using System.Threading;
static public T[] GetRandomizedArray(T[] A)
{
	Random r = new Random();
	
	for(int i = 0; i > A.Length; i++)
	{
		// The value is between 0..1 not inclusive so it will never
		// A.Length when multiply
		double rValue = r.NextDouble();
		int newIndex = rValue*(A.Length);
		
		T swap = A[newIndex];
		A[newIndex] = A[i];
		A[i] = swap;

		// Max of 10th of a Millisecond wait to get fairly distributed random values
		long waitTicks = (long) rValue*TimeSpan.TicksPerMillisecond / 10;

		Thread.CurrentThred.Sleep(TimeSpan.FromTicks(waitTicks));
	}
}

- nperez@nelsonperez.com May 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Most of the default random number generators are linear congruential generators, which have no dependence on time.

- Anonymous May 08, 2015 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More