cpp rand

C++随机数生成

470. 用 Rand7() 实现 Rand10()

给定方法 rand7 可生成 [1,7] 范围内的均匀随机整数,试写一个方法 rand10 生成 [1,10] 范围内的均匀随机整数。

你只能调用 rand7() 且不能调用其他方法。请不要使用系统的 Math.random() 方法。

每个测试用例将有一个内部参数 n,即你实现的函数 rand10() 在测试时将被调用的次数。请注意,这不是传递给 rand10() 的参数。

// The rand7() API is already defined for you.
// int rand7();
// @return a random integer in the range 1 to 7

class Solution {
public:
    int rand10() { 
        int row, col, idx;
        do{
            row = rand7();
            col = rand7();
            idx = col + (row - 1) * 7;
        }while(idx > 40);
        return 1+(idx-1) % 10;
    }
};

478. 在圆内随机生成点

给定圆的半径和圆心的位置,实现函数 randPoint ,在圆中产生均匀随机点。

实现 Solution 类:

  • Solution(double radius, double x_center, double y_center) 用圆的半径 radius 和圆心的位置 (x_center, y_center) 初始化对象
  • randPoint() 返回圆内的一个随机点。圆周上的一点被认为在圆内。答案作为数组返回 [x, y]
class Solution {
private:
    mt19937 gen{random_device{}()};
    uniform_real_distribution<double> dis;
    double xc, yc, r;

public:
    Solution(double radius, double x_center, double y_center): dis(-radius, radius), xc(x_center), yc(y_center), r(radius) {}
    
    vector<double> randPoint() {
        while (true) {
            double x = dis(gen), y = dis(gen);
            if (x * x + y * y <= r * r) {
                return {xc + x, yc + y};
            }
        }
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(radius, x_center, y_center);
 * vector<double> param_1 = obj->randPoint();
 */

398. 随机数索引

给你一个可能含有 重复元素 的整数数组 nums ,请你随机输出给定的目标数字 target 的索引。你可以假设给定的数字一定存在于数组中。

实现 Solution 类:

  • Solution(int[] nums) 用数组 nums 初始化对象。
  • int pick(int target)nums 中选出一个满足 nums[i] == target 的随机索引 i 。如果存在多个有效的索引,则每个索引的返回概率应当相等。
class Solution {
    unordered_map<int, vector<int>> mymap;
public:
    Solution(vector<int>& nums) {
        for(int i = 0; i<nums.size(); i++){
            if(mymap.count(nums[i]) == 0){
                mymap[nums[i]] = {};
                mymap[nums[i]].push_back(i);
            }else{
                mymap[nums[i]].push_back(i);
            }
        }
    }
    
    int pick(int target) {
        int index = rand() % mymap[target].size();
        return mymap[target][index];
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(nums);
 * int param_1 = obj->pick(target);
 */

 384. 打乱数组

给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是 等可能 的。

实现 Solution class:

  • Solution(int[] nums) 使用整数数组 nums 初始化对象
  • int[] reset() 重设数组到它的初始状态并返回
  • int[] shuffle() 返回数组随机打乱后的结果

Fisher-Yates 洗牌算法

class Solution {
    vector<int> &origin;
    vector<int> curr;
public:
    Solution(vector<int>& nums) : origin(nums) {
        srand(time(nullptr));
        curr.assign(nums.begin(), nums.end());
    }
    
    vector<int> reset() {
        return origin;
    }
    
    vector<int> shuffle() {
        for(int i = curr.size()-1; i >= 0; i--){
            int j = rand() % (i+1);
            swap(curr[i], curr[j]);
        }

        return curr;
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(nums);
 * vector<int> param_1 = obj->reset();
 * vector<int> param_2 = obj->shuffle();
 */

519. 随机翻转矩阵

给你一个 m x n 的二元矩阵 matrix ,且所有值被初始化为 0 。请你设计一个算法,随机选取一个满足 matrix[i][j] == 0 的下标 (i, j) ,并将它的值变为 1 。所有满足 matrix[i][j] == 0 的下标 (i, j) 被选取的概率应当均等。

尽量最少调用内置的随机函数,并且优化时间和空间复杂度。

实现 Solution 类:

  • Solution(int m, int n) 使用二元矩阵的大小 mn 初始化该对象
  • int[] flip() 返回一个满足 matrix[i][j] == 0 的随机下标 [i, j] ,并将其对应格子中的值变为 1
  • void reset() 将矩阵中所有的值重置为 0

class Solution {
    vector<int> matrix;
    int m, n;
    int total;
public:
    Solution(int _m, int _n): m(_m), n(_n){
        matrix = vector<int>(m * n, 0);
        for(int i = 0; i< m*n; i++){
            matrix[i] = i;
        }
        srand(time(nullptr));
        total = m * n;
    }
    
    vector<int> flip() {
       int index = rand() % total;
       swap(matrix[index], matrix[--total]);
       return {matrix[total] / n, matrix[total] % n};

    }
    
    void reset() {
        for(int i = total; i< m*n; i++){
            int before = matrix[total];
            swap(matrix[total], matrix[before]);
        }
        
        total = m * n;
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(m, n);
 * vector<int> param_1 = obj->flip();
 * obj->reset();
 */

 382. 链表随机节点

给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 被选中的概率一样

实现 Solution 类:

  • Solution(ListNode head) 使用整数数组初始化对象。
  • int getRandom() 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    unordered_map<int, int> mymap;
    int index;
public:
    Solution(ListNode* head) {
        ListNode *p = head;
        index = 0;
        while(p){
            mymap[index++] = p->val;
            p = p->next;
        }

        srand(time(nullptr));
    }
    
    int getRandom() {
        return mymap[rand() % index];
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(head);
 * int param_1 = obj->getRandom();
 */

497. 非重叠矩形中的随机点 

给定一个由非重叠的轴对齐矩形的数组 rects ,其中 rects[i] = [ai, bi, xi, yi] 表示 (ai, bi) 是第 i 个矩形的左下角点,(xi, yi) 是第 i 个矩形的右上角点。设计一个算法来随机挑选一个被某一矩形覆盖的整数点。矩形周长上的点也算做是被矩形覆盖。所有满足要求的点必须等概率被返回。

在给定的矩形覆盖的空间内的任何整数点都有可能被返回。

请注意 ,整数点是具有整数坐标的点。

实现 Solution 类:

  • Solution(int[][] rects) 用给定的矩形数组 rects 初始化对象。
  • int[] pick() 返回一个随机的整数点 [u, v] 在给定的矩形所覆盖的空间内。

 

class Solution {
    vector<int> nums;
    vector<pair<int,int>> coordinate;
    vector<pair<int,int>> startCoord;
    int total = 0;
public:
    Solution(vector<vector<int>>& rects) {
        for(auto &rect: rects){
            startCoord.push_back({rect[0], rect[1]});
            nums.push_back(getNums(rect));
            total += nums.back();
        }
        srand(time(nullptr));
    }

    int getNums(vector<int> &rect){
        int m = rect[2]-rect[0]+1;
        int n = rect[3]-rect[1]+1;
        coordinate.push_back({m, n});
        return m * n;
    }
    
    vector<int> pick() {
        int num = rand() % total;
        int index = 0;
        for(int i = 0; i<nums.size(); i++){
            if(num < nums[i]){
                index = i;
                break;
            }else{
                num -= nums[i];
            }
        }

        int m = coordinate[index].first, n = coordinate[index].second;

        int x = num / n, y = num % n;

        int start_x = startCoord[index].first, start_y = startCoord[index].second;

        return {start_x + x, start_y + y};
        
    }
};

/**
 * Your Solution object will be instantiated and called as such:
 * Solution* obj = new Solution(rects);
 * vector<int> param_1 = obj->pick();
 */

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值