2022-08-02:小红拿到了一个大立方体,该大立方体由1*1*1的小方块拼成,初始每个小方块都是白色。 小红可以每次选择一个小方块染成红色, 每次小红可能选择同一个小方块重复染色, 每次染色以后,

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022-08-02:小红拿到了一个大立方体,该大立方体由1*1*1的小方块拼成,初始每个小方块都是白色。 小红可以每次选择一个小方块染成红色, 每次小红可能选择同一个小方块重复染色, 每次染色以后,相关的知识,希望对你有一定的参考价值。

2022-08-02:小红拿到了一个大立方体,该大立方体由111的小方块拼成,初始每个小方块都是白色。
小红可以每次选择一个小方块染成红色,
每次小红可能选择同一个小方块重复染色,
每次染色以后,你需要帮小红回答出当前的白色连通块数,
如果两个小方块共用同一个面,且颜色相同,则它们是连通的,
给定n、m、h,表示大立方体的长、宽、高,
给定k次操作,每一次操作用(a, b, c)表示在大立方体的该位置进行染色。
返回长度为k的数组,表示每一次操作后,白色方块的连通块数。
来自网易。

答案2022-08-02:

并查集。时光倒流。

代码用rust编写。代码如下:

use rand::Rng;
fn main() 
    let size: i32 = 10;
    let test_time: i32 = 5000;
    println!("测试开始");
    for _ in 0..test_time 
        let n = rand::thread_rng().gen_range(0, size) + 1;
        let m = rand::thread_rng().gen_range(0, size) + 1;
        let h = rand::thread_rng().gen_range(0, size) + 1;
        let mut ops = random_ops(n, m, h);
        let ans1 = blocks1(n, m, h, &mut ops);
        let ans2 = blocks2(n, m, h, &mut ops);
        if ans1 != ans2 
            println!("ans1 = :?", ans1);
            println!("ans2 = :?", ans2);
            println!("出错了!");
            break;
        
    
    println!("测试结束");


// 暴力方法
// 时间复杂度(k * n * m * h);
fn blocks1(n: i32, m: i32, h: i32, ops: &mut Vec<Vec<i32>>) -> Vec<i32> 
    let mut k = ops.len() as i32;
    //int[][][] cube = new int[n][m][h];
    let mut cube: Vec<Vec<Vec<i32>>> = vec![];
    for i in 0..n 
        cube.push(vec![]);
        for j in 0..m 
            cube[i as usize].push(vec![]);
            for _ in 0..h 
                cube[i as usize][j as usize].push(0);
            
        
    
    let mut value = 1;
    let mut ans: Vec<i32> = vec![];
    for _ in 0..k 
        ans.push(0);
    
    for i in 0..k 
        cube[ops[i as usize][0] as usize][ops[i as usize][1] as usize]
            [ops[i as usize][2] as usize] = -1;
        for x in 0..n 
            for y in 0..m 
                for z in 0..h 
                    if cube[x as usize][y as usize][z as usize] != -1
                        && cube[x as usize][y as usize][z as usize] != value
                    
                        ans[i as usize] += 1;
                        infect(&mut cube, x, y, z, value);
                    
                
            
        
        value += 1;
    
    return ans;


fn infect(cube: &mut Vec<Vec<Vec<i32>>>, a: i32, b: i32, c: i32, change: i32) 
    if a < 0
        || a == cube.len() as i32
        || b < 0
        || b == cube[0].len() as i32
        || c < 0
        || c == cube[0][0].len() as i32
        || cube[a as usize][b as usize][c as usize] == -1
        || cube[a as usize][b as usize][c as usize] == change
    
        return;
    
    cube[a as usize][b as usize][c as usize] = change;
    infect(cube, a - 1, b, c, change);
    infect(cube, a + 1, b, c, change);
    infect(cube, a, b - 1, c, change);
    infect(cube, a, b + 1, c, change);
    infect(cube, a, b, c - 1, change);
    infect(cube, a, b, c + 1, change);


// 最优解
// O(k + n * m * h)
fn blocks2(n: i32, m: i32, h: i32, ops: &mut Vec<Vec<i32>>) -> Vec<i32> 
    let mut k = ops.len() as i32;
    //int[][][] red = new int[n][m][h];
    let mut red: Vec<Vec<Vec<i32>>> = vec![];
    for i in 0..n 
        red.push(vec![]);
        for j in 0..m 
            red[i as usize].push(vec![]);
            for _ in 0..h 
                red[i as usize][j as usize].push(0);
            
        
    
    for op in ops.iter() 
        red[op[0] as usize][op[1] as usize][op[2] as usize] += 1;
    
    let mut uf = UnionFind::new(n, m, h, &mut red);
    let mut ans: Vec<i32> = vec![];
    for _ in 0..k 
        ans.push(0);
    
    let mut i = k - 1;
    while i >= 0 
        ans[i as usize] = uf.sets;
        let mut x = ops[i as usize][0];
        let mut y = ops[i as usize][1];
        let mut z = ops[i as usize][2];
        red[x as usize][y as usize][z as usize] -= 1;
        if red[x as usize][y as usize][z as usize] == 0 
            // x, y ,z 这个格子,变白,建立自己的小集合
            // 然后6个方向,集合该合并合并
            uf.finger(x, y, z);
        
        i -= 1;
    
    return ans;


pub struct UnionFind 
    n: i32,
    m: i32,
    h: i32,
    father: Vec<i32>,
    size: Vec<i32>,
    help: Vec<i32>,
    sets: i32,

impl UnionFind 
    fn new(a: i32, b: i32, c: i32, red: &mut Vec<Vec<Vec<i32>>>) -> UnionFind 
        let mut n = a;
        let mut m = b;
        let mut h = c;
        let mut len = n * m * h;
        let mut father: Vec<i32> = vec![];
        let mut size: Vec<i32> = vec![];
        let mut help: Vec<i32> = vec![];
        for _ in 0..len 
            father.push(0);
            size.push(0);
            help.push(0);
        
        let mut ans = UnionFind 
            n,
            m,
            h,
            father,
            size,
            help,
            sets: 0,
        ;
        for x in 0..n 
            for y in 0..m 
                for z in 0..h 
                    if red[x as usize][y as usize][z as usize] == 0 
                        ans.finger(x, y, z);
                    
                
            
        
        return ans;
    

    pub fn finger(&mut self, x: i32, y: i32, z: i32) 
        // x,y,z
        // 一维数值
        let mut i = self.index(x, y, z);
        self.father[i as usize] = i;
        self.size[i as usize] = 1;
        self.sets += 1;
        self.union(i, x - 1, y, z);
        self.union(i, x + 1, y, z);
        self.union(i, x, y - 1, z);
        self.union(i, x, y + 1, z);
        self.union(i, x, y, z - 1);
        self.union(i, x, y, z + 1);
    

    fn index(&mut self, x: i32, y: i32, z: i32) -> i32 
        return z * self.n * self.m + y * self.n + x;
    

    fn union(&mut self, mut i: i32, x: i32, y: i32, z: i32) 
        if x < 0 || x == self.n || y < 0 || y == self.m || z < 0 || z == self.h 
            return;
        
        let mut j = self.index(x, y, z);
        if self.size[j as usize] == 0 
            return;
        
        i = self.find(i);
        j = self.find(j);
        if i != j 
            if self.size[i as usize] >= self.size[j as usize] 
                self.father[j as usize] = i;
                self.size[i as usize] += self.size[j as usize];
             else 
                self.father[i as usize] = j;
                self.size[j as usize] += self.size[i as usize];
            
            self.sets -= 1;
        
    

    fn find(&mut self, mut i: i32) -> i32 
        let mut s = 0;
        while i != self.father[i as usize] 
            self.help[s] = i;
            s += 1;
            i = self.father[i as usize];
        
        while s > 0 
            s -= 1;
            self.father[self.help[s] as usize] = i;
        
        return i;
    


// 为了测试
fn random_ops(n: i32, m: i32, h: i32) -> Vec<Vec<i32>> 
    let mut size = rand::thread_rng().gen_range(0, n * m * h) + 1;
    let mut ans: Vec<Vec<i32>> = vec![];
    for i in 0..size 
        ans.push(vec![]);
        for _ in 0..3 
            ans[i as usize].push(以上是关于2022-08-02:小红拿到了一个大立方体,该大立方体由1*1*1的小方块拼成,初始每个小方块都是白色。 小红可以每次选择一个小方块染成红色, 每次小红可能选择同一个小方块重复染色, 每次染色以后,的主要内容,如果未能解决你的问题,请参考以下文章

ecshop二级分类显示该大分类下的所有品牌

#yyds干货盘点# 动态规划专题:小红取数

大的分组中存在小的分组时,小的分组是排在该大分组后面的分组,以此类推

2022-11-30:小红拿到了一个仅由red组成的字符串 她定义一个字符e为“好e“ : 当且仅当这个e字符和rd相邻 例如“reeder“只有一个“好e“,前两个e都不是“好e“,只有第三个

2022-07-27:小红拿到了一个长度为N的数组arr,她准备只进行一次修改, 可以将数组中任意一个数arr[i],修改为不大于P的正数(修改后的数必须和原数不同), 并使得所有数之和为X的倍数。

四校联考立方体