算法与数据结构——预处理(Java)

预处理

题目一

image-20220710170459437

即每个R左边都没有G

第一种方案:左边零个染成R

第二种方案:左边一个染成R

直到全部染成R

public int minPaintTest(String s){
    char[] str=s.toCharArray();
    int N=str.length;
    int res=Integer.MAX_VALUE;
    for(int L=0;L<=N;L++){
        int help=0;
        if(L==0){
            for(int i=0;i<N;i++){
                if(str[i]=='R'){
                    help++;
                }
            }
            res=Math.min(res,help);
        }else if(L==N){
            for(int i=0;i<N;i++){
                if(str[i]=='G'){
                    help++;
                }
            }
            res=Math.min(res,help);
        }else{
            for(int i=0;i<=L;i++){
                if(str[i]=='G'){
                    help++;
                }
            }
            for(int i=L+1;i<=N;i++){
                if(str[i]=='R'){
                    help++;
                }
            }
            res=Math.min(res,help);
        }
    }
    return res;
}

时间复杂度:O(N^2)

预处理数组

预处理:某一个操作频繁,但此操作可以省掉,依次优化时间复杂度

准备两个缓存数组(类似前缀和)

两个数组分别表示0-i上有几个G、i-N上有几个R

实际代码有优化

只准备一个数组即可

public int minPaint(String s){
    if(s==null||s.length()<2){
        return 0;
    }
    char[] chs=s.toCharArray();
    int[] right=new int[chs.length];
    right[chs.length-1]=chs[chs.length-1]=='R'?1:0;
    for(int i=chs.length-2;i>=0;i--){
        right[i]=right[i+1]+(chs[i]=='R'?1:0);
    }
    int res=right[0];//全换成G的情况
    int left=0;
    for(int i=0;i<chs.length-1;i++){
        left+=chs[i]=='G'?1:0;
        res=Math.min(res,left+right[i+1]);
    }
    res=Math.min(res,left+(chs[chs.length-1]=='G'?1:0));//全换成R的情况
    return res;
}

题目二

image-20220710193917265

一个N*N的矩阵

有O(N^4)数量级的长方形

有O(N^3)数量级的正方形(从左上角的点出发,锁定边长就可以确定一个正方形)

image-20220710200855191

以上代码时间复杂度:O(N^4)

预处理

运用预处理简化遍历四条边的过程

生成两个对应的二维数组,一个表示每个数包括自己在内右边有几个连续的1

另外一个表示每个数包括自己在内下边有几个连续的1

image-20220710201310348

处理过程:

拿到一个点(x,y)后到辅助数组中看该点右边连续的1的长度是否大于border,是的话就看(x+border,y)的位置的下方;同理看(x,y)的下方是的话就跳到(x,y+border)看右方

处理过程是O(1)

总时间复杂度:O(N^3)

public static int getMaxSize(int[][] m) {
    int[][] right = new int[m.length][m[0].length];
    int[][] down = new int[m.length][m[0].length];
    setBorderMap(m, right, down);
    for (int size = Math.min(m.length, m[0].length); size != 0; size--) {
        if (hasSizeOfBorder(size, right, down)) {
            return size;
        }
    }
    return 0;
}

public static void setBorderMap(int[][] m, int[][] right, int[][] down) {
    int r = m.length;
    int c = m[0].length;
    if (m[r - 1][c - 1] == 1) {
        right[r - 1][c - 1] = 1;
        down[r - 1][c - 1] = 1;
    }
    for (int i = r - 2; i != -1; i--) {
        if (m[i][c - 1] == 1) {
            right[i][c - 1] = 1;
            down[i][c - 1] = down[i + 1][c - 1] + 1;
        }
    }
    for (int i = c - 2; i != -1; i--) {
        if (m[r - 1][i] == 1) {
            right[r - 1][i] = right[r - 1][i + 1] + 1;
            down[r - 1][i] = 1;
        }
    }
    for (int i = r - 2; i != -1; i--) {
        for (int j = c - 2; j != -1; j--) {
            if (m[i][j] == 1) {
                right[i][j] = right[i][j + 1] + 1;
                down[i][j] = down[i + 1][j] + 1;
            }
        }
    }
}


public static boolean hasSizeOfBorder(int size, int[][] right, int[][] down) {
    for (int i = 0; i != right.length - size + 1; i++) {
        for (int j = 0; j != right[0].length - size + 1; j++) {
            if (right[i][j] >= size && down[i][j] >= size
                && right[i + size - 1][j] >= size
                && down[i][j + size - 1] >= size) {
                return true;
            }
        }
    }
    return false;
}

题目三(补充:与预处理无关)

image-20220710202429877

用二进制拼

先把给的f加工成0和1的发生器

返回(0-d-c)+c

public int f(){
    return (int)(Math.random()*5)+1;
}

//等概率返回0和1的函数
public int r01(){
    int res=0;
    do{
        res=f();
    }while(res==3);
    return res<3?0:1;
}

//等概率返回1-7的函数((0-6)+1)
//三个二进制位能代表0-7的数字
public int g(){
    int res=0;
    do{
        res=(r01()<<2)+(r01()<<1)+r01();
    }while(res==7);
    return res+1;
}

image-20220710210018042

第三问调用两次f函数,出现00和11循环,出现01和10的概率一样

public int g(){
    int help1=-1;
    int help2=-1;
    do{
        help1=f();
        help2=f();
    }while(help1==help2);
    if(help1==0){
        return 0;
    }else{
        return 1;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值