Wednesday, August 24, 2011

Write a method to randomly generate a set of m integers from an array of size n. Each element must have equal probability of being chosen.

Basic Idea is run around random number generator & we need to take care of that so before moving forward we need to understand how random number generation works 
lets say you wants to generate random number between i to j e.g. [ i,j ). One standard pattern for accomplishing this is:

   (int)(Math.random() * ((Max - Min) 

This returns a value in the range [0,Max-Min).

Now you need to shift this range up to the range that you are targeting. You do this by adding the Min value.

     Min + (int)(Math.random() * ((Max - Min)

But, this is still doesn't include Max and you are getting a double value. In order to get the Max value included, you need to add 1 to your range parameter (Max - Min) and then truncate the decimal part by casting to an int. This is accomplished via:
And there you have it. A random integer value in the range [Min,Max], or per the example [5,10]:

Min + (int)(Math.random() * ((Max - Min) + 1)) 

The java Math library function Math.random() generates a double value in the range [0,1). Notice this range does not include the 1.

In order to get a specific range of values first you need to multiply by the magnitude of the range of values you want covered.
For example if you want [5,10] you need cover 5 integer values so you use
You now will get a value in the range [Min,Max). Following our example, that means [5,10):
Math.random() * ( Max - Min )
Math.random() * 5 This would return a value in the range [0,5)
Min + (Math.random() * (Max - Min))
5 + (Math.random() * (10 - 5))
Min + (int)(Math.random() * ((Max - Min) + 1))
5 + (int)(Math.random() * ((10 - 5) + 1))

Algorithm:
 
Our first instinct on this problem might be to randomly pick elements 
from the array and put them into our new subset array. But then, what 
if we pick the same element twice? Ideally, we’d want to somehow “shrink” 
the array to no longer contain that element. Shrinking is expensive though
because of all the shifting required.
 
Instead of shrinking / shifting, we can swap the element with an element 
at the beginning of the array and then “remember” that the array now only 
includes elements j and greater. That is, when we pick subset[0] to be 
array[k], we replace array[k] with the first element in the array. When 
we pick subset[1], we consider array[0] to be “dead” and we pick a random
element y between 1 and array.size(). We then set subset[1] equal to 
array[y], and set array[y] equal to array[1]. Elements 0 and 1 are
Solution:
 
class Uniform_RandomNumberGenerator
{
 /* Random number between lower and higher, inclusive */
  public static int rand(int lower, int higher)
 {
     return lower + (int)(Math.random() * (higher - lower + 1));
 }

 /* pick M elements from original array. Clone original array so that
 * we don’t destroy the input. */

 public static int[] pickMRandomly(int[] original, int m)
{
 int[] subset = new int[m];
 int[] array = original.clone();
  for (int j = 0; j < m; j++)
  {
   int index = rand(j, array.length - 1);
   subset[j] = array[index];
   array[index] = array[j]; // array[j] is now “dead”
  }
   return subset;
}

public static void main(String a[])

{  int ar[]=new int[]{2,5,3,1,4};
   int br[]=new int[5];
   br=pickMRandomly(ar,5);//n-1
      System.out.println();
   for(int i=0;i<br.length;i++)
   System.out.print(br[i] + " " );
}

}
Time Complexity: O(N)
Space Complexity: O(N)
Run Here https://ideone.com/RcBmx 
 

No comments :