简体   繁体   中英

Pick m integers randomly from an array of size n in JS

Problem (from Cracking the Coding Interview ): 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.

I'm implementing my answer in JS. For the recursive function, the code sometimes returns undefined as one of the elements in the array.

My JS Code

var pickMRecursively = function(A, m, i) {
    if (i === undefined) return pickMRecursively(A, m, A.length);
    if (i+1 === m) return A.slice(0, m);

    if (i + m > m) {
        var subset = pickMRecursively(A, m, i-1);
        var k = rand(0, i);
        if (k < m) subset[k] = A[i];

        return subset;
    }

    return null;
};

Given Java Solution

int[] pickMRecursively(int[] original, int m,int i) {
    if (i +1==m){// Basecase
     /* return first m elements of original */
    } elseif(i+m>m){
        int[] subset = pickMRecursively(original, m, i - 1); 
        int k = random value between 0 and i, inclusive
        if(k<m){
            subset[k] = original[i]j
        }
        return subset;
    }
    return null;
}

I hate these questions because sometime they're often deliberately vague - I'd ask "What type of data is in the array?". But if this is actually a question about randomly re-ordering an array, then in JavaScript, given that arr is an array of numbers, of which some/all might not be integers...

function generateM(arr) {
  var hold = [];
  var m = [];
  var n = arr.length;
  var grab;

  // clone arr >> hold
  while(n--) {
    hold[n] = arr[n];
  }
  n = hold.length;

  // select randomly from hold
  while(n--) {
    grab = hold.splice(Math.floor(Math.random()*n),1)[0];
    // ensure integers
    m.push(Math.round(grab));
  }

  return m;
}

The array arr is cloned here to cover scoping issues and to produce a fresh collection, not reorder an existing one.

ADDIT : Alternatively, if this is just asking for a set of m.length random integers generated from an array of n.length , then it doesn't matter what the content of the array actually is and the range of possible (randomly generated) values will be (could be?) 0 - n.length , so...

function generateM(arr, M) {
  var aLen = arr.length;
  var m = [];

  do {
    m.push(Math.round(Math.random() * aLen));
  } while(M--);

  return m;
}

...but that seems like a stupid, pointless challenge. The data in the 'array of size n' is quite important here it seems to me.

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