随机矩阵位置构造题——519. 随机翻转矩阵

题目


OJ平台

题目解析

首先读懂出这种问题的意图:

这是要我们随机构造得到一个符合要求的矩阵位置!注意仅仅只是得到符合要求的位置,我们不需要真正的去构建这样一个矩阵,但是我们需要通过要求模拟每次对矩阵操作的影响。

如何解题?
我们先观察每一次 flip 后的现象,由于 flip 只对没有被翻转过的位置有效(为0的位置),而每一次进行 reset 操作后,都会重置之前进行的 flip 操作。

首先我们通过一维来表示二维以方便取随机数的映射,其次我们需要进行一个 分块 的操作,这个操作主要是应对,如果随机的过程中出现不符合要求的位置(为1的位置),这说明已经被 flip 操作过。如何分块?我们想象一个连续的数组,左边一块我们分来用于随机(直接 %size 得到随机结果),如果出现碰撞,那么我们把 %size 的值映射到右半边去,比如映射到 size 位置,如果size位置还是碰撞,那么再继续映射到size的下一个映射位置。

可能大家会有一个问题:
如果我们第一次就随机的 totalSize-1 ,那会不会导致下一次再取到这个 totalSize-1 呢?
完全不用担心,因为每次取完后 total会被-1 ,那么下次无论如何都不可能被 %total 给取到了。

手写了两个具体随机过程:

解题代码

class Solution {
    
    
public:
    Solution(int m, int n) {
    
    
        this->m = m;
        this->n = n;
        this->total = m * n;
        srand(time(nullptr));
    }
    
    vector<int> flip() {
    
    
        int x = rand() % total;
        vector<int> ans; 
        // 查找位置 x 对应的映射
        if (map.count(x)) {
    
    
            int num = map[x];
            ans = {
    
    num / n, num % n};
        } else {
    
    
            ans = {
    
    x / n, x % n};
        }
        //x这个位置我们现在已经算是flip过了,所以把下一个碰撞后能够得到的位置给它准备好!
        if (map.count(total-1)) {
    
    
            map[x] = map[total-1];//如果total位置被取过,则取total位置的下一个预设位置
        } else {
    
    
            //如果total位置未被取过,则取该位置为下一次x产生碰撞的位置
            map[x] = total-1;
        }
        total--;  
        return ans;
    }
    
    void reset() {
    
    
        total = m * n;
        map.clear();
    }
private:
    int m;
    int n;
    int total;
    unordered_map<int, int> map;
};

猜你喜欢

转载自blog.csdn.net/m0_50945504/article/details/121584288