470. Implement Rand10() Using Rand7()
解法一:
这个问题腾讯二面问的,我竟然一点思路没有,说实话没刷过类似题目真的很难想到。
/**
* The rand7() API is already defined in the parent class SolBase.
* public int rand7();
* @return a random integer in the range 1 to 7
*/
class Solution extends SolBase {
public int rand10() {
int idx=40;
while(idx>=40)
{
int a=rand7();
int b=rand7();
idx=(a-1)*7+b-1;
}
return 1+idx%10;
}
}
解法二:
/**
* The rand7() API is already defined in the parent class SolBase.
* public int rand7();
* @return a random integer in the range 1 to 7
*/
class Solution extends SolBase {
public int rand10() {
int idx;
while(true)
{
int a=rand7();
int b=rand7();
idx=(a-1)*7+b;
if(idx<=40)
return 1+(idx-1)%10;
//distribute
a=idx-40;
b=rand7();
idx=(a-1)*7+b;
if(idx<=60)
return 1+(idx-1)%10;
a=idx-60;
b=rand7();
idx=(a-1)*7+b;
if(idx<=20)
return 1+(idx-1)%10;
}
}
}
class Solution {
public HashSet<Integer> set;
public int n_row;
public int n_col;
public Solution(int n_rows, int n_cols) {
set=new HashSet<>();
n_row=n_rows;
n_col=n_cols;
}
/*
3 4
0 1 2 3
4 5 6 7
8 9 10 11
*/
public int[] flip() {
int[] ret=new int[2];
if(n_col==0 || n_row==0)
return ret;
int rand;
while(true)
{
rand=(int)(Math.random()*(double)this.n_row*this.n_col);
if(!set.contains(rand))
break;
}
ret[0]=rand/n_col;
ret[1]=rand%n_col;
set.add(rand);
return ret;
}
public void reset() {
this.set=new HashSet<>();
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(n_rows, n_cols);
* int[] param_1 = obj.flip();
* obj.reset();
*/
class Solution {
public int[] right;
public int sum;
public Solution(int[] w) {
sum=0;
right=new int[w.length];
for(int i=0;i<w.length;i++)
{
sum+=w[i];
right[i]=sum;
}
}
public int pickIndex() {
double target=Math.random()*sum;
int i=0;
for(;i<right.length;i++)
{
if(target<=right[i])
break;
}
return i;
}
}
497. Random Point in Non-overlapping Rectangles
因为要返回被矩形区域覆盖的整数坐标点,累计计算的不是矩形的面积,而应该是点的数量(包括矩形边上的点),另外生成的随机数范围因该注意
class Solution {
public int[] areas;
public int[][] rects;
public Solution(int[][] rects) {
this.areas=new int[rects.length];
this.rects=rects;
for(int i=0;i<rects.length;i++)
{
int[] rect=rects[i];
areas[i]=(rect[2]-rect[0]+1)*(rect[3]-rect[1]+1);
}
for(int i=1;i<areas.length;i++)
areas[i]+=areas[i-1];
}
public int[] pick() {
int target=(int)(Math.random()*(this.areas[this.rects.length-1]+1));
int[] ret=new int[2];
if(rects.length==0)
return ret;
int i=0;
for(;i<this.rects.length;i++)
{
if(target<=this.areas[i])
break;
}
int[] rect=this.rects[i];
ret[0]=rect[0]+(int)(Math.random()*(rect[2]-rect[0]+1));
ret[1]=rect[1]+(int)(Math.random()*(rect[3]-rect[1]+1));
return ret;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(rects);
* int[] param_1 = obj.pick();
*/
解法二:
基本思路一样,但是在搜索步骤采用了TreeMap来降低查询时间复杂度,当然也可以使用二分法。
class Solution {
TreeMap<Integer, Integer> map; //将累积点数(key)与矩形的索引(value)存储在map中
int[][] arrays;
int sum;
Random rnd= new Random();
public Solution(int[][] rects) {
arrays = rects;
map = new TreeMap<>();
sum = 0;
for(int i = 0; i < rects.length; i++) {
int[] rect = rects[i];
// the right part means the number of points can be picked in this rectangle
sum += (rect[2] - rect[0] + 1) * (rect[3] - rect[1] + 1);
map.put(sum, i);
}
}
public int[] pick() {
// nextInt(sum) returns a num in [0, sum -1]. After added by 1, it becomes [1, sum]
int c = map.ceilingKey( rnd.nextInt(sum) + 1);
return pickInRect(arrays[map.get(c)]);
}
private int[] pickInRect(int[] rect) {
int left = rect[0], right = rect[2], bot = rect[1], top = rect[3];
return new int[]{left + rnd.nextInt(right - left + 1), bot + rnd.nextInt(top - bot + 1) };
}
}
478. Generate Random Point in a Circle
采用reject sampling算法
class Solution {
public double x;
public double y;
public double r;
public Solution(double radius, double x_center, double y_center) {
x=x_center;
y=y_center;
r=radius;
}
public double[] randPoint() {
double dx,dy;
do{
dx=(2*Math.random()-1)*this.r;
dy=(2*Math.random()-1)*this.r;
}while(dx*dx+dy*dy>r*r);
double[] ret=new double[2];
ret[0]=x+dx;
ret[1]=y+dy;
return ret;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(radius, x_center, y_center);
* double[] param_1 = obj.randPoint();
*/
极坐标法:
class Solution {
public double x;
public double y;
public double r;
public Solution(double radius, double x_center, double y_center) {
x=x_center;
y=y_center;
r=radius;
}
public double[] randPoint() {
double angle=Math.random()*360;
double radius=Math.sqrt(Math.random())*this.r;
double dx=radius*Math.cos(angle*Math.PI/180);
double dy=radius*Math.sin(angle*Math.PI/180);
double[] ret=new double[2];
ret[0]=x+dx;
ret[1]=y+dy;
return ret;
}
}