【华为OD题库-034】字符串化繁为简-java

题目

给定一个输入字符串,字符串只可能由英文字母(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
题目应该是对输出字符串是忽略大小写的,否则按照不同方式处理会得到不同的结果。
解题思路如下:

  1. 首先提取小括号内的字符放入set中去重,小括号内字符个数大于1时才放入set
  2. 将其他字符(非小括号内的字符)组成新字符串:newStr
  3. 对set中的字符按照字典序排序,并转为字符数组:chars
  4. 对newStr中遍历,当某个字符出现在chars中时,将它替换为chars[0]
  5. 最后输出newStr即可

关键在于第1、2步,即将输入字符串分离为括号内字符和括号外字符两部分
我们可以使用栈stack来实现,使用sb(StringBuilder)存放括号外的字符,使用set存放括号内的字符,将输入字符串转为chars数组,遍历chars:

  1. 如果stack为空时,说明没有出现括号,直接把字符加入sb
  2. 如果stack不为空或者字符串为(时,说明已经出现了括号,或者第一次出现括号,直接把字符加入stack
  3. 如果遇到 ),代表一对括号结束,应该清除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),查看当前专栏更新的所有题目。

说明

本专栏所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_31076523/article/details/134176793。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

  • 26
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值