题目
给定一个输入字符串,字符串只可能由英文字母(a ~ z、A ~ Z)和左右小括号()组成。当字符里存在小括号时,小括号是成对的,可以有一个或多个小括号对,小括号对不会嵌套,小括号对内可以包含1个或多个英文字母也可以不包含英文字母。当小括号对内包含多个英文字母时,这些字母之间是相互等效的关系,而且等效关系可以在不同的小括号对之间传递,即当存在a和b等效和存在b和c等效时,a和c 也等效,另外,同一个英文字母的大写字和小写字母也相互等效(即使它们分布在不同的括号对里)。
要对这个输入字符串做简化,输出一个新的字符串,输出字符串里只需保留输入字符串里的没有被小括号对包含的字符(按照输入字符串里的字符顺序),并将每个字符替换为在小括号对里包含的字典序最小的等效字符。如果简化后的字符串为空,请输出为"0"
示例:输入字符串为"never(dont)live(run)up(f)()“,初始等效字符集合为(d,o,n,t,r,u,n),由于等效关系可以传递,因此最终等效字符集合为(d,n,o,r,t,u),将输入字符串里的剩余部分按字典序最小的等效字符替换后得到"devedlivedp”
输入描述
input string
输入为1行,代表输入字符串
输出描述
output string
输出为1行,代表输出字符串
备注
输入字符串的长度在1~100000之间
示例1:
输入∶
()abd
输出:
abd
说明:
输入字符串里没有被小括号包含的字符串为"abd",其中每个字符没有等效字符,输出为"abd"
示例2:
输入∶
(abd)demand(fb)()for
输出:
aemanaaor
说明:
等效字符集为(a,b,d, f),输入字符串里没有被小括号包含的字符串集合为demandfor”,将其中字符替换为字典序最小的等效字符后输出为:“aemanaaor”
示例3:
输入∶
happy(xyz)new(wxy)year(t)
输出:
happwnewwear
说明:
等效字符集为(w,x,y,z),输入字符串里没有被小括号包含的字符串集合为"happynewyear”,将其中字符替换为字典序最小的等效字等后输出为:“happwnewwear”
思路
比如输入的字符串为:NeVeD(dont)Live(Drun)up(f)()
按照题意:
先提取小括号(括号内字符数大于1)里的字符:dontDrun,去重后为,dDontru。由于大小写是等效的,所以这里如果转为全小写并去重排序后的结果为:dnortu。于是现在需要将原来字符串中的d,n,o,r,t,u,全部转为d。得到字符串:deVedLivedp
但是当我们全转为大写时,将原来字符串中的d,n,o,r,t,u,全部转为D,得到结果:DeVeDLiveDp
题目应该是对输出字符串是忽略大小写的,否则按照不同方式处理会得到不同的结果。
解题思路如下:
- 首先提取小括号内的字符放入set中去重,小括号内字符个数大于1时才放入set
- 将其他字符(非小括号内的字符)组成新字符串:newStr
- 对set中的字符按照字典序排序,并转为字符数组:chars
- 对newStr中遍历,当某个字符出现在chars中时,将它替换为chars[0]
- 最后输出newStr即可
关键在于第1、2步,即将输入字符串分离为括号内字符和括号外字符两部分
我们可以使用栈stack来实现,使用sb(StringBuilder)存放括号外的字符,使用set存放括号内的字符,将输入字符串转为chars数组,遍历chars:
- 如果stack为空时,说明没有出现括号,直接把字符加入sb
- 如果stack不为空或者字符串为(时,说明已经出现了括号,或者第一次出现括号,直接把字符加入stack
- 如果遇到 ),代表一对括号结束,应该清除stack。并且还需要根据括号对中的字符数量判断是否加入set中。怎么判断数量?此时stack中的字符为:(、若干字符(stack.size-1),如果字符数量大于1,那么应该将stack中除最后一个(外的字符加入set。
最后考虑特殊情况,比如按照括号对分离后sb为空,直接输出0,set为空,则直接输出sb.toString()
题解
package hwod;import java.util.*;public class StringSimplifying {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String str = sc.nextLine();System.out.println(stringSimplifying(str));}private static String stringSimplifying(String str) {Set<Character> set = new HashSet<>();//存储括号内的字符StringBuilder sb = new StringBuilder();//存储括号外的字符LinkedList<Character> queue = new LinkedList<>();for (int i = 0; i < str.length(); i++) {if (str.charAt(i) == ')') {if (queue.size() - 1 > 1) {while (queue.size() > 1) {set.add(Character.toLowerCase(queue.pollLast()));//大小写等效,全转为小写}}queue.clear();continue;}if (str.charAt(i) == '(' || !queue.isEmpty()) {queue.addLast(str.charAt(i));continue;}sb.append(str.charAt(i));}if (sb.length() == 0) {return "0";}if (set.size() == 0) {return sb.toString();}ArrayList<Character> chars = new ArrayList<>(set);Collections.sort(chars);final char[] newChars = sb.toString().toCharArray();for (int i = 0; i < newChars.length; i++) {if (chars.contains(Character.toLowerCase(newChars[i]))) {newChars[i] = chars.get(0);}}return String.valueOf(newChars);}
}
推荐
如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。