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即可.

猜你喜欢

转载自blog.csdn.net/kelly_fumiao/article/details/84991629