算法-数据预处理

数据预处理

我们在写代码是发现有地方是需要重复查询的,我们就要考虑是否可以使用数据预处理,后面直接查询预处理的数据,不用再进行重复查询

题目描述

牛牛有一些排成一行的正方形。每个正方形已经被染成红色或者绿色。牛牛现在可以选择任意一个正方形然后用这两种颜色的任意一种进行染色,这个正方形的颜色将会被覆盖。牛牛的目标是在完成染色之后,每个红色R都比每个绿色G距离最左侧近。牛牛想知道他最少需要涂染几个正方形。 如样例所示: s = RGRGR 我们涂染之后变成RRRGG满足要求了,涂染的个数为2,没有比这个更好的涂染方案。

题意就是将R全部放左边,将G全部在右边,R和G的最终数量是不确定的,例如RGRGR,我们只需要将第二个G染成R,最后一个R然后G,这样就形成了RRRGG。

输入描述

输入包括一个字符串s,字符串s长度length(1 ≤ length ≤ 50),其中只包括’R’或者’G’,分别表示红色和绿色。

输出描述

输出一个整数,表示牛牛最少需要涂染的正方形数量 示例1 输入 RGRGR 输出 2

基础解法

	public static int minPaint(String s) {
		
		char[] str = s.toCharArray();
		
		int N = str.length-1;
		
		int res = Integer.MAX_VALUE;
		// 左:R   右:G
		// 依次查找左边为(0-N)个R时的染色情况
		for (int i=0;i<=N;i++) {
			
			// 当左侧为0个R时,右侧必须全为G,所以我们查出右侧R的数量就是染色的数量
			if (i == 0) {
				res = Math.min(res,RGNums(str,0,N,'R'));
			}
			// 当左侧为N个R时,左侧必须全为R,所以我们查出左侧G的数量就是染色的数量
			else if (i == N) {
				res = Math.min(res,RGNums(str,0,N,'G'));
			}
			// 其他时候我们就查出0-i范围上G的数量,i+1-N范围上R的数量,两者加起来就是染色的数量
			else {
				int a = RGNums(str,0,i,'G');
				int b = RGNums(str,i+1,N,'R');
				res = Math.min(res,a+b);
			}
		}
		
		return res;
	}
	
	/*
		在str数组中L-R的范围内右多少个c字符
	 */
	private static int RGNums(char[] str,int L,int R,char c) {
		
		int res = 0;
		for (int i = L;i<=R;i++) {
			if (str[i] == c) {
				res++;
			}
		}
		
		return res;
	}

我们发现要不停的计算一定范围内R,G的值,所以我们是否可以提前将这些数据计算出来,我们拿着计算出来的数据使用就好,这个就不需要重复计算了,只用计算一次。
我们生成两个辅助数组arrA,arrB,arrA统计0-N范围上G的数量,如果要将前k个染为R,问只需要将前k个内的G染色即可,arrB统计N-0范围上R的数量,如果要将后面的染为G,我们只需要统计后面的R的数量,所以创建两个这个的数组。

	public static int minPaint1(String s) {
		
		char[] str = s.toCharArray();
		
		int N = str.length-1;
		
		// 生成辅助数组
		int[] arrA = getHelpArrA(str,N,'G');
		int[] arrB = getHelpArrB(str,N,'R');
		
		int res = Integer.MAX_VALUE;
		// 左:R   右:G
		// 依次查找左边为(0-N)个R时的染色情况
		for (int i=0;i<=N;i++) {
			
			// 当左侧为0个R时,右侧必须全为G,所以我们查出右侧R的数量就是染色的数量
			if (i == 0) {
				res = Math.min(res,arrB[0]);
			}
			// 当左侧为N个R时,左侧必须全为R,所以我们查出左侧G的数量就是染色的数量
			else if (i == N) {
				res = Math.min(res,arrA[i]);
			}
			// 其他时候我们就查出0-i范围上G的数量,i+1-N范围上R的数量,两者加起来就是染色的数量
			else {
				res = Math.min(res,arrA[i]+arrB[i]);
			}
		}
		
		return res;
	}
	
	private static int[] getHelpArrA(char[] str,int R,char c) {
		
		int[] arrA = new int[R+1];
		int res = 0;
		for (int i = 0;i<=R;i++) {
			if (str[i] == c) {
				arrA[i] = ++res;
			}else {
				arrA[i] = res;
			}
		}
		
		return arrA;
	}
	
	private static int[] getHelpArrB(char[] str,int R,char c) {
		
		int[] arrB = new int[R+1];
		int res = 0;
		for (int i = R;i>=0;i--) {
			if (str[i] == c) {
				arrB[i] = ++res;
			}else {
				arrB[i] = res;
			}
		}
		
		return arrB;
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值