成對符號截取字符串面試題

在羣聊天中偶然看到這一問題,用代碼實現了一下。java

實現思路是用數組接收傳入的成對符號,循環遍歷數組,將數組內0,1每兩個當作一對,每次循環+2,而後在while循環中每次從開始查找成對符號,若是找到開始如(和結束如),則取出並標記開始符號在整個字符串的位置,用於後序排序。實現思路有點複雜了,直接上代碼了。數組

第一種實現app

package com;ui

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{.net

                     //這個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);
        
    }rem

}
運行後輸出的結果爲:字符串

傳入的字符串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這種狀況傳入的數組爲() {}  【】 改變順序或獲得不一樣的字符串結果。get

-------------------------------------------------------------------------------------------------------string

上面只是初級的代碼實現

請看下面代碼 第二種實現

主要用正則截取的,用到外循環,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等,可能須要更復雜的實現。我的小白,能力有限。

在此拋磚引玉了,但願有興趣的大神們踊躍發表本身的意見,歡迎評論。

相關文章
相關標籤/搜索