Substring with Concatenation of All Words leetcode java


題目:

You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters.

For example, given:
S: "barfoothefoobarman"
L: ["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

 

題解:

我最開始做的是說把L里面給的串全排列放起來,看S包含不包含其中之一,包含的話反話其index。但是這個方法TLE了

代碼:

 

 1     public  static  void swap(String[] str,  int i,  int j){  
 2         String temp =  new String();  
 3         temp = str[i];  
 4         str[i] = str[j];  
 5         str[j] = temp; 
 6     } 
 7     
 8      public  static  void arrange (String[] L,  int st, ArrayList<String> re){
 9          if (st == L.length - 1){
10             String temp =  new String();
11              for ( int i = 0; i < L.length; i ++){
12                 temp +=L[i];
13             }  
14             re.add(temp);
15         } else{
16              for ( int i = st; i < L.length; i ++){  
17                 swap(L, st, i);  
18                 arrange(L, st + 1,re);  
19                 swap(L, st, i);  
20             }  
21         }  
22          return ;
23     }  
24      public  static ArrayList<Integer> findSubstring(String S, String[] L) {
25         ArrayList<Integer> result =  new ArrayList<Integer>();
26         ArrayList<String> possible =  new ArrayList<String>();
27         arrange(L,0,possible);
28         
29          for( int j= 0; j<possible.size();j++){
30              if(S.contains(possible.get(j)))
31                 result.add(S.indexOf(possible.get(j)));     
32         }
33        
34          return result;
35     }

 更好的解法就是一種滑動窗口式的。我是參照了http://blog.csdn.net/linhuanmars/article/details/20342851的寫法,他的寫法目前速度最快。

 首先是先把所給的字典利用HashMap建一下,key存word,value存這個word出現的個數。

 因為每個單詞長度一樣,外層循序只許循環wordLen次,每次指針挪一次,每一次循環遍歷整個字符串。

 內層循環每次遍歷一個單詞,把整個S字符串遍歷檢查。

 需要在每次大循環維護一個count,看是不是達到了給的字典字符串數量,同時維護一個index,是每個符合條件的字符串的起始index,需要存到返回結果中。

 為了能夠檢查是不是合格字符串,在這里維護一個curDict的HashMap。

 

 首先檢查一個單詞是不是在原始字典中出現,沒出現的話說明這個單詞肯定不符合標准,index指針指向下一個單詞的起始點,計數器和curDict都要清零。

 如果這個單詞在原始字典里出現過,用更新原始字典的方法更新curDict,如果這個單詞出現的次數沒有超過原始字典里記錄的次數,那么count++,如果超過了,就需要挪動指針,並把超過的從curDict刪掉。

 最后,如果count達到了L的length,說明找到了一個合格的字符串,那么將index存入返回結果res中,再把index挪到下一個單詞處,更新curDict即可。

 

code ganker的講解是這樣的:

這道題看似比較復雜,其實思路和Longest Substring Without Repeating Characters差不多。因為那些單詞是定長的,所以本質上和單一個字符一樣。和Longest Substring Without Repeating Characters的 區別只在於我們需要維護一個字典,然后保證目前的串包含字典里面的單詞有且僅有一次。思路仍然是維護一個窗口,如果當前單詞在字典中,則繼續移動窗口右 端,否則窗口左端可以跳到字符串下一個單詞了。假設源字符串的長度為n,字典中單詞的長度為l。因為不是一個字符,所以我們需要對源字符串所有長度為l的 子串進行判斷。做法是i從0到l-1個字符開始,得到開始index分別為i, i+l, i+2*l, ...的長度為l的單詞。這樣就可以保證判斷到所有的滿足條件的串。因為每次掃描的時間復雜度是O(2*n/l)(每個單詞不會被訪問多於兩次,一次是窗 口右端,一次是窗口左端),總共掃描l次(i=0, ..., l-1),所以總復雜度是O(2*n/l*l)=O(n),是一個線性算法。空間復雜度是字典的大小,即O(m*l),其中m是字典的單詞數量。


代碼部分我自己稍作了修改,主題思想與code ganker相同。

代碼如下:

 1       public  static ArrayList<Integer> findSubstring(String S, String[] L) { 
 2          ArrayList<Integer> res =  new ArrayList<Integer>();
 3           if(S== null||L== null||S.length()==0||L.length==0)
 4              return res;
 5           int wordLen = L[0].length(); // same length for each word in dictionary
 6           
 7            // put given dictionary into hashmap with each word's count
 8           HashMap<String, Integer> dict =  new HashMap<String, Integer>();
 9           for(String word: L){
10               if(!dict.containsKey(word))
11                 dict.put(word, 1);
12               else
13                 dict.put(word, dict.get(word) + 1);
14          }
15          
16           for( int i = 0; i < wordLen; i++){
17               int count = 0;
18               int index = i; // index of each startpoint
19               HashMap<String, Integer> curdict =  new HashMap<String, Integer>();
20               // till the first letter of last word 
21                for( int j = i; j <= S.length() - wordLen; j += wordLen){
22                  String curWord = S.substring(j, j + wordLen);
23                   // check each word to tell if it existes in give dictionary
24                    if(!dict.containsKey(curWord)){
25                      curdict.clear();
26                      count = 0;
27                      index = j + wordLen;
28                  } else{
29                       // form current dictionary
30                        if(!curdict.containsKey(curWord))
31                         curdict.put(curWord, 1);
32                       else
33                         curdict.put(curWord, curdict.get(curWord) + 1);
34                      
35                       // count for current found word and check if it exceed given word count
36                        if(curdict.get(curWord) <= dict.get(curWord)){
37                          count++;
38                      } else{
39                           while(curdict.get(curWord) > dict.get(curWord)){
40                              String temp = S.substring(index, index + wordLen);
41                              curdict.put(temp, curdict.get(temp)-1);
42                              index = index + wordLen; // make index move next
43                           }
44                      }
45                      
46                       // put into res and move index point to nextword 
47                        // and update current dictionary as well as count num
48                        if(count == L.length){
49                          res.add(index);
50                          String temp = S.substring(index, index + wordLen);
51                          curdict.put(temp, curdict.get(temp)-1);
52                          index = index + wordLen;
53                          count--;
54                      }
55                  }
56              } // end for j
57           } // end for i
58             return res;
59         } 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM