2019.8.3猿辅导研发笔试第一题题解(Java实现):解压缩字符串

问题描述

就是处理字符串,给定的字符串如下所示:

A3B,处理后的结果为 AAAB
(AB)2C,处理后的结果为 ABABC
((AB)2C)2D, 处理后的结果为 ABABCABABCD

字符后的数字代表重复次数,带括号的表示括号内的都是重复的。
 

输入描述

第一行为一个整数 K,代表有 K 个待处理的字符串。
之后的 K 行都是待处理的字符串。
 

输出描述

输出 K 个处理后的字符串

输入举例:

3
A3B
(AB)2C
((AB)2C)2D

输出举例:

AAAB
ABABC
ABABCABABCD

 

代码实现

先说一下算法思想:

  1. 首先遍历字符串,找到字符串中最后一个出现的左括号:"(",与第一个出现的右括号:")",找到这俩字符的下标位置,这是为了找到最里层的括号,因为处理多层括号嵌套的情况,需要从内向外的处理。
  2. 如果步骤1没找到,说明字符串是这种格式的:A3B2,不存在括号,直接处理完返回处理后的字符串即可。(同时这也是递归的终止情况)
  3. 如果步骤1找到了,那就只处理最内层的一对括号,处理完直接递归调用即可,就是再执行一次同样的逻辑。这样能保证,总会有一次,字符串中不再存在括号,到这一次的时候,会执行步骤2,能保证递归的终止。

注:下面的代码是 Java 实现的,不过女朋友不会 Java,只会 C/C++,所以注释里写了很多解释 Java 语言特性的废话,本文也是为了给她写题解顺便水了一篇文章。。。

上代码

public class Main{
	
	//Java的主函数,类似于C/C++的main,程序的入口
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);//Java 读取控制台输入的方法
		int num = in.nextInt();//获取字符串个数
		
		//一共num个字符串,循环num次
		while(num > 0) {
			String s = in.next();// 获取当前待处理的字符串
			String res = helper(s);// 这里 helper 函数是处理字符串的核心
			System.out.println(res);// Java 中的打印方式
			num--;
		}
	}
	
	
	private static String helper(String s) {
		StringBuilder sb = new StringBuilder();// Java中处理多个字符串想拼接的一个高效方法,你不用理解这块
		
		int lastLeftIndex = -1; // 最后一个出现的左括号所在的下标位置。
		int firstRightIndex = s.length(); // 第一个出现的右括号所在的下标位置。
		
		//确定 lastLeftIndex 和 firstRightIndex 的过程
		for(int i = 0; i < s.length(); i++) {
			char c = s.charAt(i); // Java中获取某个字符串当前下标位置的字符的方法。
			if (c == '(') {
				lastLeftIndex = i;
			}
			if (c == ')') {
				firstRightIndex = i;
				break; // 找到第一个出现的右括号所在的下标位置后,直接break跳出循环即可。
			}
		}
		
		//如果 lastLeftIndex 为 -1,说明没有括号了,直接处理就可以,同时这里也是递归的终止条件
		if (lastLeftIndex == -1) {
			
			//注意循环的终止条件,这里不会处理最后一个字符,所以循环体外需要额外检查一下最后一个字符
			for(int i = 0; i < s.length() - 1; i++) {
				char c = s.charAt(i); //当前字符
				
				//这里需要判断,字符 c 后面的字符是否是数字字符。
				//isCharNum 方法,是用来判断某个字符是否是数字字符的,实现在最下面。
				if (isCharNum(s.charAt(i + 1))) {
					int j = i + 1;
					
					//如果下标 j 所对应的字符是数字字符,那就一直递增 j ,直到 j 超过字符串大小或者j不再是数字字符。
					while(j < s.length() && isCharNum(s.charAt(j))) j++;
					
					String numStr = s.substring(i + 1,j);// 将数字字符串截取出来。
					int repeatNum = Integer.parseInt(numStr);// 获取到重复次数
					
					//根据重复次数,添加重复的字符
					while(repeatNum > 0) {
						sb.append(c);
						repeatNum--;
					}
					
					//之后令 i 为 j - 1即可,并且 continue 直接进入下次循环。
					i = j - 1;
					continue;
				}
				
				//如果 i + 1 所对应的字符不是数字字符,直接加上字符c即可
				sb.append(c);
			}
			
			//要额外检查一下最后一个字符,看它是否是数字字符,如果是的话,那么我们上面的for循环就已经处理完毕了
			//如果不是的话就需要添加上这最后的字符
			char lastChar = s.charAt(s.length() - 1);
			if (!isCharNum(lastChar)) sb.append(lastChar);
			return sb.toString();//递归终止
		}
		
		//如果 lastLeftIndex 不是 -1,说明字符串中存在括号,接下来我们处理存在括号的情况
		//1.首先直接截取最后一个左括号之前的字符串,将其原封不动的加入 sb(StringBuilder)中
		String leftString = s.substring(0,lastLeftIndex);
		sb.append(leftString);
		
		//2.之后解压缩最内层括号内的字符串
		//首先获取最内层括号内的字符串
		String curString = s.substring(lastLeftIndex + 1,firstRightIndex);
		
		//之后获取该括号内字符串的重复次数,并循环重复次数将 curString 加入 sb
		int j = firstRightIndex + 1;
		while(j < s.length() && isCharNum(s.charAt(j))) j++;
		String numString = s.substring(firstRightIndex + 1,j);
		int repeatNum = Integer.parseInt(numString);
		while(repeatNum > 0) {
			sb.append(curString);
			repeatNum--;
		}
		
		//3.最后直接将,从 j 开始一直到字符串结尾的部分加入 sb 即可
		String rightString = s.substring(j,s.length());
		sb.append(rightString);
		
		//递归处理
		return helper(sb.toString());
	}
	
	//判断某个字符是否是数字,即'0'~'9'
	private static boolean isCharNum(char c) {
		return c - '0' >= 0 && c - '9' <= 0; 
	}
	
}

你可能感兴趣的:(笔试面试)