成对符号截取字符串面试题

在群聊天中偶然看到这一问题,用代码实现了一下。

实现思路是用数组接收传入的成对符号,循环遍历数组,将数组内0,1每两个看成一对,每次循环+2,然后在while循环中每次从开始查找成对符号,如果找到开始如(和结束如),则取出并标记开始符号在整个字符串的位置,用于后序排序。实现思路有点复杂了,直接上代码了。

第一种实现

package com;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
 * 
 * 截取成对符号内的字符串并用","隔开输出
 * 可同时传入多个成对符号
 * @author ss
 *
 */
public class StrTrim{
    
    public static void main(String[] args) {
        String str="(asj)d[f]adf{dd}d[asd]f{cccc}a(sdf)fh[k]j(vv)df[a]as{dddd}df";
        String [] arr={"(",")","[","]","{","}"};
        System.out.println("输出的结果为:"+subStr(arr,str));
        
    }
    
    public static String subStr(String[] arr,String str){
        
        //获取值放进list集合
        StringBuffer sb=new StringBuffer();
        //最终result
        StringBuffer rsb=new StringBuffer();
        //存储每次截取的符号对在字符串开始位置
        List<Integer> numsList=new ArrayList<Integer>();
        //存储每次截取的字符串
        List<String> list=new ArrayList<String>();
        //临时字符串
        String temp="";
        //在字符串开始  结束为止
        int start =0,end=0;
        //截取后剩余的
        String remain="";
        //保留原传进的值
        String ostr=str;
        
        for (int i = 0; i < arr.length; i+=2) {
            remain=str;
            int num=0;
            while(remain.contains(arr[i]) && remain.contains(arr[i+1])){
                start =remain.indexOf(arr[i]);
                end=remain.indexOf(arr[i+1]);
                if( start < end ){
                    sb.append(remain.substring(start+1, end)).append(",");
                    temp=remain.substring(start+1, end);
                    list.add(temp);
                    //总长度-剩余长度+start开始位置 为当前坐标值
                    num=str.length()-remain.length()+start;
                    //System.out.println(num + "---" + "str length--"+ str.length() + "--remain-" +remain.length()+"--start="+start);
                    remain=remain.substring(end+1,remain.length());
                    numsList.add(num);
                }else{

                     //这个break好像只能跳出if循环,不能跳出while循环,下面看另一个案例

                      //想跳出while内的循环得用 outer:while(true){  //逻辑     break outer;}
                    break;
                }
            }
        }
        
        //将截取的值和位置存进map集合
        Map<String, String> map = new TreeMap<String, String>();
        for (int j = 0; j < list.size(); j++) {
                ostr=ostr.replace(list.get(j), "");
                map.put(String.valueOf(numsList.get(j)), list.get(j));
        }
        //将位置集合排序 从小到大
        Collections.sort(numsList);
        //取出最终排序后的结果
        for (int i = 0; i < numsList.size(); i++) {
            //System.out.println("key="+numsList.get(i)+"----value="+map.get(String.valueOf(numsList.get(i))));
            rsb.append(map.get(String.valueOf(numsList.get(i)))).append(",");
        }
        
        System.out.println("传入的字符串str="+str);
        System.out.println("传入的成对符号为:arr="+Arrays.asList(arr).toString());
        System.out.println("截取到的字符串集合为list="+list.toString());
        
        return rsb.toString().substring(0,rsb.length()-1);
        
    }

}
运行后输出的结果为:

传入的字符串str=(asj)d[f]adf{dd}d[asd]f{cccc}a(sdf)fh[k]j(vv)df[a]as{dddd}df
传入的成对符号为:arr=[(, ), [, ], {, }]
截取到的字符串集合为list=[asj, sdf, vv, f, asd, k, a, dd, cccc, dddd]
输出的结果为:asj,f,dd,asd,cccc,sdf,k,vv,a,dddd
总结,虽然能实现了,但由于按传入的成对符号的先后顺序迭代,导致传入的数组顺序不同,可能会输出结果不同,如bb{ 【(a)】}cc这种情况传入的数组为() {}  【】 改变顺序或得到不同的字符串结果。

-------------------------------------------------------------------------------------------------------

上面只是初级的代码实现

扫描二维码关注公众号,回复: 831272 查看本文章

请看下面代码 第二种实现

主要用正则截取的,用到外循环,switch case 和正则里的一些方法,while迭代后进入两种情况像是开关的两条路,总之感觉比第一种方法高大上了好多,不足的是对于字符串中存在的半个括号问题会报错。只要传入的字符串是规则的有开始结束成对符号的,截取都是没问题的。

public static String getS(String str,StringBuilder newStr){
        if(str.length()<=0){
            return newStr.toString().substring(1);
        }
        Pattern pattern = Pattern.compile("[\\{\\}\\[\\]()<>《》]"); 
        Matcher matcher = pattern.matcher(str); 
        int i=0,begin=0,end=0;
        outer:
        while(matcher.find()) {
            String group=matcher.group(0);
            switch(i){
                case 0:{
                    begin=str.indexOf(group);
                    i++;
                    continue;
                }
                case 1:{
                    end=str.indexOf(group);
                    newStr.append(","+str.substring(begin+1,end));
                    i++;
                    continue;
                }
                default:break outer;
            }
        }
        return getS(str.substring(end+1),newStr);
    }
 

最终总结:感觉写代码少经验不足,都会用最基础的思想或逻辑去实现功能,比如能用if else不会用switch case,能用冒泡排序不会用collections.sort()方法,而且对外循环基本不了解。虽然第一种方法能实现但可看出其实现思路和方法还是很复杂的,但代码的优雅性并不高,像是用砖盖起的一个结构复杂的房子,感觉第二种代码简单,实现思路和代码质量比较高,至少用的的带花纹的瓷砖盖起的房子。由此也感觉到自己的功底不足。

虽然再往深挖两种思路都有问题或不足,但更需要明白的是功能实现要以需求为准,如果再解析更复杂的字符串如alsk【as{sd[sdf]f}d】djf等,可能需要更复杂的实现。个人小白,能力有限。

在此抛砖引玉了,希望有兴趣的大神们踊跃发表自己的意见,欢迎评论。

猜你喜欢

转载自my.oschina.net/u/2301293/blog/983066
今日推荐