原文地址 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;
}