栅栏涂色题

题目:
在这里插入图片描述

注意
在使用 nextInt() 后再使用nextLine() ,则需要将中间的换行符用 nextLine() 提取出来,然后才是输入的字符串,也就是说 要用两次 nextLine() !

思路:

  1. 遍历两次,
    第一次从左边出发,遍历到 i 位置,用lr数组记录将 i 左边全修改为红色的次数,用lb数组记录将 i 左边全修改为蓝色的次数;
    第二次从右边出发,遍历到 i 位置,用rr数组记录将 i 左边全修改为红色的次数,用rb数组记录将 i 左边全修改为蓝色的次数;

  2. 符合题意的是颜色一边一半,或者全为一种颜色,那么需要求出 每个位置对应的 左右两边各修改为红 或 蓝的次数中的最小值,并按索引位置记录在 res数组中;

  3. 最后遍历res数组,找出哪个位置需要修改的次数最少的,就算答案

特殊情况:

如果输入为 r r b r r 时,当遍历到 i=2 ,即 ’ b‘ 时,左边修改为全红次数是0,全蓝次数是2;右边修改为全红次数是0,全蓝次数是2,两边各选取最小值,即0+0 ,最后答案是0 ;
显然 0 不对!因为忽略了 ’b‘ 本身和两侧都不一样!
所以对这种情况先进行判断 : if(i>1 && c[i]!=c[i-1] && c[i]!=c[i+1]) 即 当前元素和两边都不同时,就将结果+1 !

Java实现:

public class Main{
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        String blank=in.nextLine();
        String s=in.nextLine();
        char[] c = s.toCharArray();

        int[] lr=new int[n]; // 左边出发,i 位置需要改为红的次数
        int[] lb=new int[n]; // 左边出发,i 位置需要改为蓝的次数

        int[] rr=new int[n]; // 左边出发,i 位置需要改为红的次数
        int[] rb=new int[n]; // 左边出发,i 位置需要改为蓝的次数
        // lr lb 左边出发 ,记录i个位置左边都改为全红/蓝的 次数
        for(int i=0;i<n;i++){ //遍历每个 i
            for(int j=0;j<i;j++){ // 遍历 i 左边改的次数
                if(c[j]=='b'){ // 为蓝则需要改一次
                    lr[i]=lr[i]+1; // 存储 第i个位置左边全改为 红r的次数
                }
                if(c[j]=='r'){ // 为红则需要改一次
                    lb[i]=lb[i]+1; // 存储 第i个位置左边全改为 blue的次数
                }
            }
        }


        // rr rb 右边出发 ,记录i个位置左边都改为全红/蓝的 次数
        for(int i=n-1;i>=0;i--){ //遍历每个 i
            for(int j=n-1;j>i;j--){ // 遍历右边 改的次数
                if(c[j]=='b'){ // 为蓝则需要改一次
                    rr[i]=rr[i]+1; // 存储 第i个位置左边全改为 红r的次数
                }
                if(c[j]=='r'){ // 为红则需要改一次
                    rb[i]=rb[i]+1; // 存储 第i个位置左边全改为 红r的次数
                }

            }
        }
        
        // 用left和right记录每个位置 左起改为某色最小次数、和右起改为某色最小次数
        // res[]记录每个位置修改成功共需要的次数
        int[] res=new int[n];
        for(int i=0;i<n;i++){
            int left=Math.min(lr[i],lb[i]); // 左改为全红or全蓝 最小
            int right=Math.min(rr[i],rb[i]);// 右改为全红or全蓝 最小
            if(i>1 && c[i]!=c[i-1] && c[i]!=c[i+1]){ // 如果是 r b r 情况,遍历到b时要+1
                res[i]=left+right+1;
            }else{
                res[i]=left+right;
            }
        }
        //最后求最小
        int min=Integer.MAX_VALUE;
        for(int i=0;i<n;i++){
            min=Math.min(min,res[i]);
        }
        System.out.println(min);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值