1. 程式人生 > >Random Pick Index(398)

Random Pick Index(398)

398—Random Pick Index

Given an array of integers with possible duplicates, randomly output the index of a given target number. You can assume that the given target number must exist in the array.

Note:
The array size can be very large. Solution that uses too much extra space will not pass the judge.

Example 1:

int[] nums = new int[] {1,2,3,3,3};
Solution solution = new Solution(nums);
// pick(3) should return either index 2, 3, or 4 randomly. Each index should have equal probability of returning.
solution.pick(3);
// pick(1) should return 0. Since in the array only nums[0] is equal to 1.
solution.pick(1);

C程式碼:

#include <stdlib.h>

typedef struct {
  int *nums;
  int numsSize;
} Solution;

Solution* solutionCreate(int* nums, int numsSize) {
  Solution *obj = (Solution*) malloc(sizeof(Solution));
  obj->nums = nums;
  obj->numsSize = numsSize;
  return obj;
}

int solutionPick(Solution*
obj, int target) { // 方法一:直接把nums中所有等於target的index記錄在陣列中,再隨機. // int result[1000]={0}; //存放nums中等於target的index // int count = 0; //nums中等於下標的個數 // for(int i = 0; i< obj->numsSize; i++) { // if(obj->nums[i] == target) { // result[count++] = i; // } // } // if (count == 1) { // return result[0]; // } // return result[rand()%count]; // 方法二: 水塘抽樣(Reservoir Sampling) int count = 0; int result = -1; int randomNum = -1; for(int i = 0; i<obj->numsSize;i++) { if(obj->nums[i] != target) continue; if(count == 0){ result = i; count++; }else { count++; randomNum = rand()%count; if(randomNum < 1) { result = i; } } } return result; } void solutionFree(Solution* obj) { free(obj); }

Complexity Analysis:

Time complexity : O(n).
Space complexity : O(1).

思路:

int* reservoirSampling(int *nums, int numsSize) {
  int reservoirSize = 5;
  static int reservoir[5];
  int i = 0;

  //先把水塘裝滿
  for (i = 0; i < reservoirSize;i++)
    reservoir[i] = nums[i];

  int randomNum;
  for(i = reservoirSize;i < numsSize;i++) {
    randomNum = rand()%(i+1);
    if(randomNum < reservoirSize) {
      reservoir[randomNum] = nums[i];
    }
  }
  return reservoir;
}

本題目相當於Sample 為nums中等於target的值的集合, 樣本容量(reservoirSize)為1. 事實上保證第k個樣本來時,它留下概率為reservoirSize/k即可.