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

将以下代码转换为python:function newpop=zmutate(pop,popsize,pm1,pm2,fitness1,M,N,Tn0,Tn1,Q,ST0,maxT,t,maxgen,LCR,ECR,MCR,FC,ICR) %M为辅助坑道数量;N为单元数 x=pop(:,1:2*M+1);%分段点位置 y=pop(:,2*M+2:4*M+2);%是否选择该分段点 z=pop(:,4*M+3:6*M+4);%开挖方向 W=pop(:,6*M+5:8*M+6);%作业班次 lenx=length(x(1,:)); leny=length(y(1,:)); lenz=length(z(1,:)); lenW=length(W(1,:)); avefit=sum(fitness1)/popsize; worstfit=min(fitness1); % sumy=sum(y); % lenz=sumy+1; % lenW=sumy+1; for i=1:popsize %选择popsize次,每次选择一个,输出一个 %随机选择一个染色体 pick=rand; while pick==0 pick=rand; end index=ceil(pick*popsize); f1=fitness1(index); if f1<=avefit % pm=(exp(-t/maxgen))*(pm1-(pm1-pm2)*(f1-avefit)/max(fitness1)-avefit); pm=1/(1+exp(t/maxgen))*(pm1-(pm1-pm2)*(f1-avefit)/max(fitness1)-avefit); else % pm=(exp(-t/maxgen))*pm1; pm=1/(1+exp(t/maxgen))*pm1; end pick=rand; while pick==0 pick=rand; end if pick>pm continue; end % flag0=0; % while(flag0==0) %随机选择变异位置 pick1=rand; pick2=rand; pick3=rand; pick4=rand; while pick1*pick2*pick3*pick4==0 pick1=rand; pick2=rand; pick3=rand; pick4=rand; end posx=ceil(pick1*lenx); posy=ceil(pick2*leny); %x,y变异 randx=randi([1,N-1]); while ismember(randx,x(index,:)) randx=randi([1,N-1]); end b=x(index,posx); x(index,posx)=randx; a=[0 1]; c=y(index,posy); y(index,posy)=setxor(y(index,posy),a); %z,W变异 posz=ceil(pick3*lenz); posW=ceil(pick4*lenW); d=z(index,posz); z(index,posz)=setxor(z(index,posz),a); randW=randi([1,3]); while randW==W(index,posW) randW=randi([1,3]); end e=W(index,posW); W(index,posW)=randW; mpop=[x(index,:),y(index,:),z(index,:),W(index,:)]; mtime=ztime(mpop,M,N,Tn0,Tn1,Q,ST0); mutfit=zcost(mpop,M,N,mtime(:,1),mtime(:,2:2*M+3),mtime(:,2*M+4:2*M+2+N),LCR,ECR,MCR,FC,ICR,Q); if mtime(:,1)>maxT||mutfit<=worstfit x(index,posx)=b; y(index,posy)=c; z(index,posz)=d; W(index,posW)=e; end end newpop=[x,y,z,W]; end
最新发布
05-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值