简体   繁体   中英

Generating Random Numbers from 1-100

int getnum50()
{ 
  Random rand = new Random(); 
  return (1+rand.nextInt(50)); 
}    
  • You are given a predefined function named getnum50() which returns an integer which is one random number from 1-50.
  • You can call this function as many times as you want but beware that this function is quite resource intensive.
  • You cannot use any other random generator. You can NOT change the definition of getnum50() .

Print numbers 1-100 in random order. (Not 100 random numbers)

Note:

  • i. Every number should be printed exactly once.
  • ii. There should be no pattern in the numbers listing. List should be completely random ie, all numbers have equal probability appearing at any place.
  • iii. You may call getnum50() any number of time to get random number from 1 to 50 but try to make the code optimised.
  • iv. You cannot use any other random generator function except getnum50().

I wrote some code which was showing correct output.

import java.util.Random;

public class RandomInteger{

    int number[]=new int[100];//To store numbers in random order

    public RandomInteger(){
        int n[]=new int[100];//array to store which random numbers are generated
        int off[]={-1,0};//offset to add
        System.out.println("Length of array number100 is:"+number.length);
        System.out.println("Generating  random numbers in the range 1-100:");
        for(int n1=0;n1<number.length;n1++){
            int rnd=off[(getnum50()-1)/50]+(getnum50()*2);
            if(n[rnd-1] == 0){
                n[rnd-1]=1;//to indicate which random number is generated
                number[n1]=rnd;
                System.out.println(number[n1]+" ");
            }
        }
    }
    //end of constructor

    int getnum50(){  
        Random rand = new Random(); 
        return (1+rand.nextInt(50));      
    }

    public static void main(String args[]){
        RandomInteger m= new RandomInteger();
    }
    //end of main()
}
//end of class

While it was accepted in that round, in the next round the interviewer tells me that getnum50() is a costly method and even in best case scenario I have to call it twice for every number generated. ie 200 times for 1-100. In worst case scenario it would be infinity and tens of thousand in average case. He asks me to optimize the code so as to significantly improve the average case. I could not answer.So please give me proper answer for the question? How will I optimize my above code??

One stupid optimization would be be to just realize that since your randomized source is limited to 1-50, you might as well set TWO array positions, eg

rand = getnum50();
n[rand] = 1;
n[rand+50] = 1;

Now the array will be slightly "less" random, because every index n is going simply be 1/2 of whatever's at n+50 , but at least you've cut ~half the build array construction time.

I think they want you to produce a shuffle algorithm.

In this, you start with an array of exactly 100 numbers ( 1 through 100 in order ), and then on each iteration you shuffle the numbers.

Do it enough times, and the original array is completely random.

The 50 is a red herring. Use two calls to random50, mod 10. Now you have two digits: tens and ones place. This gives you a random100() function.

The real killer is the generate-and-check approach. Instead, put the numbers 1-100 into an arraylist, and use your random100 to REMOVE a random index. Now your worst case scenario has 2n calls to random50. There's a few problems left to solve - overruns - but that's the approach I'd look at.

The reason you are calling the method getnum50() twice is because of this line:

int rnd = off[(getnum50()-1)/50] + (getnum50()*2);

which seems self-explanatory. And the reason your worst case scenario is so bad is because of this block:

if(n[rnd - 1] == 0){
    n[rnd - 1] = 1;          //to indicate which random number is generated
    number[n1] = rnd;
    System.out.println(number[n1] + " ");
}

Depending on how bad your luck is, it could take a very long time to get each value. So, best case, you make your two getnum50() calls, which WILL happen the first time, but as you fill up your array, it becomes increasingly less likely. For 100 numbers, the last number will have a 1% chance of success on the first time, and every time it fails, you make another two calls to getnum50().

Sorry, this doesn't answer HOW to improve your efficiency, but it does explain why the efficiency concerns. Hope it helps.

Your problem us that if you are toward the end of the list you will have to generate lots of random numbers to get a number in the couple of spots left. You could reduce a couple of ways one the fits into your current answer fairly will is as follows:

  while(n[rnd-1] == 1)
  {
    rnd++;
    rnd=end%101;
  }
  n[rnd-1]=1;//to indicate which random number is generated
  number[n1]=rnd;
  System.out.println(number[n1]+" ");

However if you assume that the getnum50 is more expensive than anything you can write you could reduce the number of getnum50 that you call while filling in the second half of the list. Each time you find a number you could reduce your search space by one so (using non primitives):

while(myArrayList.size()>1)
{
   int rnd=0;
   if(myArrayList.size()>50);
     rnd=((getnum50()-1)/50)+((getnum50()*2)%myArrayList.size())+1;
   else
     rnd=getnum50()%myArrayList.size()+1;
   System.out.println(rnd);
   myArrayList.remove(rnd);
}
System.out.println(myArrayList.get(rnd);
myArrayList.remove(rnd);

In this example your best, average and worst are 149 getnum50 calls;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM