华为笔试0410第二题——字符串展开

目录

  • 题目描述
    • 输入描述
    • 输出描述
    • 示例
  • 解法一:压栈法
    • 测试结果
  • 解法二:递归法
    • 测试结果
  • 解法三:指针法
    • 测试结果
  • 算法复杂度分析

题目描述

给定一个字符串,字符串包含数字、大小写字母以及括号(包括大括号、中括号和小括号),括号可以嵌套,即括号里面可以出现数字和括号。

按照如下的规则对字符串进行展开,不需要考虑括号成对不匹配问题,用例保证括号匹配,同时用例保证每个数字后面都有括号,不用考虑数字后面没有括号的这种情况,即2a2(b)这种情况不用考虑。

1)数字表示括号里的字符串重复的次数,展开后的字符串不包含括号。
2)将字符串进行逆序展开。

输出最终展开的字符串。

输入描述

输入一个长度小于100的字符串。

输出描述

输出展开后的字符串。

示例

输入

abc3(A)

输出

AAAcba

解法一:压栈法

import java.util.*;

public class Solution {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String str = in.next();
		System.out.println(reverseInStack(str));
	}
	
	public static String reverseInStack(String str) {
		Stack<Character> stack = new Stack<>();
		ArrayList<Character> list = new ArrayList<>();
		//把大括号和中括号全部替换为小括号;
		str = str.replace('{','(').replace('}', ')');
		str = str.replace('[','(').replace(']', ')');
		char[] chars = str.toCharArray();
		int i=0;		
		while(true) {
			//入栈直到遇到第一个右括号;
			while(i < chars.length && chars[i]!=')') {
				stack.push(chars[i]);
				i++;
			}
			//出栈直到遇到最近的左括号,并依次倒入表中;
			while(stack.peek()!='(') {
				list.add(stack.pop());
				if(stack.empty()) break;
			}
			if(stack.empty()) break;
			//左括号出栈;
			stack.pop();
			//检测左括号左边是否为数字,若是记为n,否则记为1;
			int n;
			if(stack.peek()>'0' && stack.peek()<='9')
				n = stack.pop() - '0';
			else n = 1;
			//把括号内的字符循环n遍;
			ArrayList<Character> list2 = new ArrayList<>();
			while(n > 0) {
				list2.addAll(list);
				n--;
			}
			//清空线性表,因为每次出栈前list必须是空表;
			list.clear();
			//将list2逆序倒入栈中;
			for(int j = list2.size()-1; j>=0; j--) {
				stack.push(list2.remove(j));
			}	
			//右括号不能入栈,因此i指针还要后移一位;
			i++;
		}
		//遍历list,输出;
		StringBuilder sb= new StringBuilder();
	    for (Character character : list) {
	        sb.append(character);
	    }
	    return sb.toString();
	}
}

测试结果

在这里插入图片描述

解法二:递归法

import java.util.*;

public class Solution {

	public static void main(String[] args) {
		Scanner in =  new Scanner(System.in);
		String str = in.next();
		//把大括号和中括号全部替换为小括号;
		str = str.replace('{','(').replace('}', ')');
		str = str.replace('[','(').replace(']', ')');
		char[] chars = str.toCharArray();
		int[] index = {chars.length-1};
		System.out.println(reverseByRecursion(chars,index));
	}
	
	public static String reverseByRecursion(char[] chars,int[] index) {
		String str = "";
		//从后往前遍历;
		while(index[0] >= 0) {
			if(chars[index[0]] != '(' && chars[index[0]] != ')') {
			//不是括号,则直接反转;
				str += chars[index[0]];
				index[0]--;
			}
			else if(chars[index[0]] == '(') {
			//找到左括号,提取左边的数字进行复制操作;
				String tmp = str;
				for(int i = 1; i<chars[index[0]-1]-'0'; i++) {
					tmp += str;
				}
				str = tmp;
				//越过前两位,即左括号位和数字位;
				index[0] -= 2;
				return str;
			}
			else if(chars[index[0]] == ')') {
			//找到右括号,递归处理括号内部的子串;
				index[0]--;
				str += reverseByRecursion(chars,index);
			}
		}
		return str;
	}
}

测试结果

在这里插入图片描述

解法三:指针法

import java.util.*;

public class Solution {
    
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String str = in.next();
		System.out.println(reverseByPointor(str));
	}
	
    public static String reverseByPointor(String str) {
    	//把大括号和中括号全部替换为小括号;
		str = str.replace('{','(').replace('}', ')');
		str = str.replace('[','(').replace(']', ')');
    	StringBuffer sb = new StringBuffer(str);
        int i = 0;
        while (i < sb.length()) {
        	//i指针从左往右遍历直到找到右括号;
            if (sb.charAt(i) == ')') {
            	//j指针指向右括号的左一位,左右往左遍历直到找到左括号;
                int j = i - 1;
                while (sb.charAt(j) != '(') {
                    j--;
                }
                //括号里面为空,将括号删除;
                if (j == i - 1) {
                    sb.replace(j , i + 1, "");
                } else {
                	//定义一个StringBuffer用来存储局部处理后的字符串;
                    StringBuffer sb1 = new StringBuffer();
                    if (1 <= (sb.charAt(j - 1) - '0') && (sb.charAt(j - 1) - '0') <= 9) {
                        int m = sb.charAt(j - 1) - '0';
                        for (int p = 1; p <= m; p++) {
                            sb1.append(sb.substring(j + 1, i));
                        }
                        //将原字符串括号及内部子串替换为sb1;
                        sb.replace(j - 1, i + 1, sb1.toString());
                        //调整下标;
                        i = j + sb1.length() - 1;
                    } else {//没有数字,视作数字为1;
                    	sb1.append(sb.substring(j + 1, i));
                    	sb.replace(j, i + 1, sb1.toString());
                    	i = j + sb1.length() - 1;
                    }
                }
            } else {
                i++;
            }
        }
        return sb.reverse().toString();
    }
}

测试结果

在这里插入图片描述

算法复杂度分析

解法 时间复杂度 空间复杂度
压栈法 O ( n ) O(n) O(n) O ( n ) O(n) O(n)
递归法 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)
指针法 O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)

你可能感兴趣的:(编程题)