2019大廠面試題,據說90%的人當場沒寫對(題解)

原文地址 2019大廠面試題,據說90%的人當場沒寫對,30%寫出思路得了部分分數。看到很多人用了正則,貌似還做的都不對。以下時我的解題過程和代碼。如有不對請指正(代碼是java代碼)。樓主800ms的要求,這邊實際是150ms 當然還可以繼續優化。

題目

需要在字符串y中尋找:含有字符串x所有字符的最短字符串
說明:
如果 y 中不存這樣的最短字符串,則返回空字符串 ""。
如果 y 中存在這樣的最短字符串,返回任意一個最短匹配。

例子:
輸入: y = "dhs5goe13j45ddsfoea", x = "esd"
輸出: "dsfoe"

難得對一道算法題感興趣,看到題目瞬間想到的是逆向思維,先對x去重,用set就行了

將y轉數組,在java中 string 本身就是個char數組,所以直接 y.toCharArray()就完事了

接着將y數組按set 值進行分組,如果分組數量等於 x_set數量,則肯定存在,否則直接返回不存在。

事例如下以例子作爲分析事例

e[6,17]

s[2,14]

d[0,13,12]

用以上三個數組組成list,即 List<Map<Character,List<Interger>>>   list,然後對list 按 map的 value 中的list.size(進行升序排列),然後取最少個數的數組。也就是 取出e[6,17] 或者 2[2,14]並對其遍歷,x中含有不重複的元素個數是3 那麼,最短字符串可能爲三個元素相鄰,次之中四個元素,再次之5個元素,依此類推,就能夠在找到最短字符串時停止,而不需要一遍歷整個樹,當然最極端情況就是遍歷全部,這裏還可以進行優化,暫不討論。  這裏以 y_char[6]爲頂點半徑爲3 開始遍歷。如果不存在,則到y_char[17]爲頂點,半徑爲3開始遍歷,如果不存在,則 回到 y_char[6]半徑爲4,如果不存在則到 y_char[17]半徑爲4,直到遍歷到匹配字符爲止。

第一次口述算法,講的不是很好,多多見諒,看代碼吧。

具體代碼如下(樓主要求以下事例執行耗時800ms),以下事例實際耗時 150ms;

public static void main(String[] args) {
        String y = "obzcopzocynyrsgsarijyxnkpnukkrvzuwdjldxndmnvevpgmxrmvfwkutwekrffnloyqnntbdohyfqndhzyoykiripdzwiojyoznbtogjyfpouuxvumtewmmnqnkadvzrvouqfbbdiqremqzgevkbhyoznacqwbhtrcjwfkzpdstpjswnpiqxjhywjanhdwavajrhwtwzlrqwmombxcaijzevbtcfsdcuovckoalcseaesmhrrizcjgxkbartdtotpsefsrjmvksqyahpijsrppdqpvmuocofuunonybjivbjviyftsyiicbzxnwnrmvlgkzticetyfcvqcbjvbufdxgcmesdqnowzpshuwcseenwjqhgsdlxatamysrohfnixfprdsljyyfhrnnjsagtuihuczilgvtfcjwgdhpbixlzmakebszxbhrdibpoxiwztshwczamwnninzmqrmpsviydkptjzpktksrortapgpxwojofxeasoyvyprjoguhqobehugwdvtzlenrcttuitsiijswpogicjolfxhiscjggzzissfcnxnvgftxvbfzkukqrtalvktdjsodmtgzqtuyaqvvrbuexgwqzwduixzrpnvegddyyywaquxjxrnuzlmyipuqotkghfkpknqinoidifnfyczzonxydtqroazxhjnrxfbmtlqcsfhshjrxwqvblovaouxwempdrrplefnxmwrwfjtebrfnfanvvmtbzjesctdgbsfnpxlwihalyiafincfcwgdfkvhebphtxukwgjgplrntsuchyjjuqozakiglangxkttsczhnswjksnuqwflmumpexxrznzwxurrysaokwxxqkrggytvsgkyfjrewrcvntomnoazmzycjrjrqemimyhriyxgrzcfuqtjhvjtuhwfzhwpljzajitrhryaqchnuawbxhxrpvyqcvhpggrpplhychyulijhkglinibedauhvdydkqszdbzfkzbvhldstocgydnbfjkcnkfxcyyfbzmmyojgzmasccaahpdnzproaxnexnkamwmkmwslksfpwirexxtymkmojztgmfhydvlqtddewjvsrmyqjrpycbmndhupmdqqabiuelacuvxnhxgtpvrtwfgzpcrbhhtikbcqpctlxszgpfbgcsbaaiapmtsucocmpecgixshrrnhyrpalralbccnxvjzjllarqhznzghswqsnfuyywmzbopyjyauknxddgdthlabjqtwxpxwljvoxkpjjpfvccyikbbrpdsyvlxscuoofkecwtnfkvcnzbxkeabtdusyhrqklhaqreupakxkfzxgawqfwsaboszvlshwzhosojjotgyagygguzntrouhiweuomqptfjjqsxlbylhwtpssdlltgubczxslqjgxuqnmpynnlwjgmebrpokxjnbiltvbebyytnnjlcwyzignmhedwqbfdepqakrelrdfesqrumptwwgifmmbepiktxavhuavlfaqxqhreznbvvlakzeoomykkzftthoemqwliednfsqcnbexbimrvkdhllcesrlhhjsspvfupxwdybablotibypmjutclgjurbmhztboqatrdwsomnxnmocvixxvfiqwmednahdqhxjkvcyhpxxdmzzuyyqdjibvmfkmonfxmohhshpkhmntnoplphqyprveyfsmsxjfosmicdsjrieeytpnbhlsziwxnpmgoxneqbnufhfwrjbqcsdfarybzwaplmxckkgclvwqdbpumsmqkswmjwnkuqbicykoisqwoootrdpdvcuiuswfqmrkctsgrevcxnyncmivsxbpbxzxpwchiwtkroqisnmrbmefbmatmdknaklpgpyqlsccgunaibsloyqpnsibwuowebomrmcegejozypjzjunjmeygozcjqbnrpakdermjcckartbcppmbtkhkmmtcngteigjnxxyzaibtdcwutkvpwezisskfaeljmxyjwykwglqlnofhycwuivdbnpintuyhtyqpwaoelgpbuwiuyeqhbvkqlsfgmeoheexbhnhutxvnvfjwlzfmvpcghiowocdsjcvqrdmkcizxnivbianfpsnzabxqecinhgfyjrjlbikrrgsbgfgyxtzzwwpayapfgueroncpxogouyrdgzdfucfrywtywjeefkvtzxlwmrniselyeodysirqflpduvibfdvedgcrzpzrunpadvawfsmmddqzaaahfxlifobffbyzqqbtlcpquedzjvykvarayfldvmkapjcfzfbmhscdwhciecsbdledspgpdtsteuafzbrjuvmsfrajtulwirzagiqjdiehefmfifocadxfuxrpsemavncdxuoaetjkavqicgndjkkfhbvbhjdcygfwcwyhpirrfjziqonbyxhibelinpllxsjzoiifscwzlyjdmwhnuovvugfhvquuleuzmehggdfubpzolgbhwyeqekzccuypaspozwuhbzbdqdtejuniuuyagackubauvriwneeqfhtwkocuipcelcfrcjcymcuktegiikyosumeioatfcxrheklookaqekljtvtdwhxsteajevpjviqzudnjnqbucnfvkybggaybebljwcstmktgnipdyrxbgewqczzkaxmeazpzbjsntltjwlmuclxirwytvxgvxscztryubtjweehapvxrguzzsatozzjytnamfyiitreyxmanhzeqwgpoikcjlokebksgkaqetverjegqgkicsyqcktmwjwakivtsxjwrgakphqincqrxqhzbcnxljzwturmsaklhnvyungjrxaonjqomdnxpnvihmwzphkyuhwqwdboabepmwgyatyrgtboiypxfavbjtrgwswyvcqhzwibpisydtmltbkydhznbsvxktyfxopwkxzbftzknnwipghuoijrbgqnzovxckvojvsqqraffwowfvqvfcmiicwitrhxdeombgesxexedlakitfovtydxunqnwqqdeeekiwjnwoshqcsljiicgobbbuqakjdonjawgjlezdnqhfdqnmsuavxdpnfzwipmspiabveaarshzwxmirgkmfncvtdrdvfxkpxlkdokxgtwcskmjryyymcthfnkasinihaunohkxaibtsqelockaefjmsuolebtnepauwmrxutspjwaxbmahsjtkfkxlnszribmeofbkyvbjscjtqjakuwvcgunvnonvqbbggfshauqsyznokqbhowjusypfnecffenojfvlblgzntqzlrgzprvhqnpfrrkzxznieiuivajivzijsqijigtatifmbplzqahuidegfoobpymkputzamzvweiyvvzlwihgmmmrcburbgbsdxrfjsbiylitghgcpqjbevvgypxcybubyoijijrhuzcdijfybqbfowlookqmlnplbxvjjosfqviygqyhgamuwzjklbyzopkrnhbywtfoqomweldmlrhjqswctubiknzzvcztyehouvnyiqnvkufaobehxhrjvtisxjlxoumipzjarwvbsaegdkpbsjmpevjbewzuqnfhoohhmdjgfpmjzdmtmykqvtucptwfidpwtwffzolffzqfdearclkyeecuzabjeqhxpmfodsvisnpxrqowdawheydfyhoexvcmihdlzavtqlshdhdgjzpozvvackebhgqppvcrvymljfvooauxcjnbejdivikcoaugxwzsulgfqdtefpehbrlhaoqxwcancuvbqutnfbuygoemditeagmcveatgaikwflozgdhkyfqmjcruyyuemwbqwxyyfiwnvlmbovlmccaoguieu";
        String x = "cjgamyzjwxrgwedhsexosmswogckohesskteksqgrjonnrwhywxqkqmywqjlxnfrayykqotkzhxmbwvzstrcjfchvluvbaobymlrcgbbqaprwlsqglsrqvynitklvzmvlamqipryqjpmwhdcsxtkutyfoiqljfhxftnnjgmbpdplnuphuksoestuckgopnlwiyltezuwdmhsgzzajtrpnkkswsglhrjprxlvwftbtdtacvclotdcepuahcootzfkwqhtydwrgqrilwvbpadvpzwybmowluikmsfkvbebrxletigjjlealczoqnnejvowptikumnokysfjyoskvsxztnqhcwsamopfzablnrxokdxktrwqjvqfjimneenqvdxufahsshiemfofwlyiionrybfchuucxtyctixlpfrbngiltgtbwivujcyrwutwnuajcxwtfowuuefpnzqljnitpgkobfkqzkzdkwwpksjgzqvoplbzzjuqqgetlojnblslhpatjlzkbuathcuilqzdwfyhwkwxvpicgkxrxweaqevziriwhjzdqanmkljfatjifgaccefukavvsfrbqshhswtchfjkausgaukeapanswimbznstubmswqadckewemzbwdbogogcysfxhzreafwxxwczigwpuvqtathgkpkijqiqrzwugtr";


        long start=System.currentTimeMillis();
        find(x,y);
        long end=System.currentTimeMillis();
        System.out.println("總耗時"+(end-start)+"ms");
    }

    public static void find(String x,String y){
        char[] x_chars=x.toCharArray();
        char[] y_chars=y.toCharArray();
        Set<Character> x_set=new HashSet<Character>();
        //對x去重
        for (char x_char : x_chars) {
            x_set.add(x_char);
        }
        //對y中元素按x分組
        List<Map<Character,List<Integer>>> list=new ArrayList<Map<Character, List<Integer>>>();
        for (Character character : x_set) {
            List<Integer> x_array=new ArrayList<Integer>();
            for (int i = 0; i <y_chars.length ; i++) {
                if (character==y_chars[i]){
                    x_array.add(i);
                }
            }
            Map<Character,List<Integer>> map=new TreeMap<Character, List<Integer>>();
            if(x_array.size()>0){
                map.put(character,x_array);
                list.add(map);
            }
        }

        if (x_set.size()!=list.size()){
            System.out.println("y中不存在這樣的數據");
            return ;
        }
        //對分組後的每組數據個數按從小到大進行排序
        Collections.sort(list, new Comparator<Map<Character, List<Integer>>>() {
            public int compare(Map<Character, List<Integer>> m1, Map<Character, List<Integer>> m2) {
                return m1.entrySet().iterator().next().getValue().size()-m2.entrySet().iterator().next().getValue().size();
            }
        });
        //取個數最小的進行計算
        Map<Character, List<Integer>> minMap = list.get(0);

        List<Integer> value = minMap.entrySet().iterator().next().getValue();

        int step=x_set.size();
        //根據步長進行查找從最小得開始即x所有字符個數
        out:for (int i=step;i<=y_chars.length;i++){
            //先廣度查找,找不到逐步深度查找
            for (Integer pos : value) {
                String str=find(pos,i,x_set.size(),y_chars,x_set);
                if (str!=null){
                    System.out.println(str);
                    break out;
                }
            }
        }
    }

    /**
     * @param pos 遊標位置
     * @param step 步長
     * @param size x_set長度
     * @param y_chars 要查詢的數組
     * @return
     */
    private static String find(int pos,int step,int size,char[] y_chars,Set<Character> x_set){
        //如果(位置-步長)超過y_chars 的開始位置取開始位置
        int start=pos-step>0?pos-step:0;
        //如果(位置+步長)超過y_chars 的結束位置取結束位置
        int end=pos+step>y_chars.length?y_chars.length:pos+step;
        for (int i = start; i <=pos; i++) {
            Set<Character> set=new HashSet<>();
            for (int j = 0; j < step; j++) {
                if (i+j>=end){
                    break;
                }
                //判斷獲取到的值是否包含在 x中,如果不包含無需存放
                if (x_set.contains(y_chars[i+j])){
                    set.add(y_chars[i+j]);
                }
            }
            if (set.size()==size){
                return new String(subChars(y_chars,i,i+step));
            }
        }
        return null;
    }

    /** char數組截取
     * @param src
     * @param begin
     * @param end
     * @return
     */
    public static char[] subChars(char[] src, int begin, int end) {
        char[] cs = new char[end-begin];
        System.arraycopy(src, begin, cs, 0, end-begin);
        return cs;
    }

 

 

 

 

 

發佈了119 篇原創文章 · 獲贊 28 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章