標籤:exp hash this line only ati cad span count
A string S of lowercase letters is given. We want to partition this string into as many parts as possible so that each letter appears in at most one part, and return a list of integers representing the size of these parts.
Example 1:
Input: S = "ababcbacadefegdehijhklij"Output: [9,7,8]Explanation:The partition is "ababcbaca", "defegde", "hijhklij".This is a partition so that each letter appears in at most one part.A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits S into less parts.
Note:
S will have length in range [1, 500].
S will consist of lowercase letters (‘a‘ to ‘z‘) only.
分析:題目翻譯一下:給定一個字串,要求將字串分區,使得每一片中出現的字元僅在這個分區中出現。第一個思路:用一map儲存每個字串出現的次數,如果走到某個字元處,前面所有字元對應的值都為0,那麼就說明這個分區找到了。根據這個原理,可以寫出下面代碼:
1 class Solution { 2 public List<Integer> partitionLabels(String S) { 3 Map<Character,Integer> map = new HashMap<>(); 4 Set<Character> set = new HashSet<>(); 5 List<Integer> list = new ArrayList<>(); 6 7 for ( char c : S.toCharArray() ) 8 map.put(c,map.getOrDefault(c,0)+1); 9 //System.out.println(map);10 11 int left = 0;12 int count = 0;13 while ( left < S.length() ){14 char c = S.charAt(left);15 set.add(c);16 map.put(c,map.get(c) - 1);17 count += 1;18 boolean ise = true;19 for ( char temp : set ){20 if ( map.get(temp) != 0 ) ise = false;21 }22 if ( ise ){23 list.add(count);24 count = 0;25 set.clear();26 }27 left ++;28 }29 return list;30 }31 }
已耗用時間42ms,非常耗時。不過這個方法是最直觀的方法。下面分析如何改進。
第二個思路:上一個方法是不停的對map進行-1操作,然後判斷是否為0。這個題目也可以用map來儲存每個字元最後出現的位置,並且用一個變數儲存前面出現過的字元中最遠的位置。如果cur指標走到這個位置,就說明前面的都被訪問過了,就得到了這個分區。show me the code:
1 class Solution { 2 public List<Integer> partitionLabels(String S) { 3 Map<Character,Integer> map = new HashMap<>(); 4 List<Integer> list = new ArrayList<>(); 5 6 for ( int i = 0 ; i < S.length() ; i ++ ) 7 map.put(S.charAt(i),i); 8 9 int left = 0, right = 0, cur = 0;10 while ( cur < S.length() ){11 char c = S.charAt(cur);12 right = Math.max(right,map.get(c));13 if ( cur == right ){14 list.add(right-left+1);15 left = right+1;16 }17 cur++;18 }19 return list;20 }21 }
已耗用時間14ms,擊敗36.70%,還是很慢。為什麼呢?
第三個思路:其實也不散完整的思路,對上面進行改進,因為map工作量比較大,因此不妨用一個26長度的數組取代map(這個方法在用到map和字串的時候非常常見)。
1 class Solution { 2 public List<Integer> partitionLabels(String S) { 3 List<Integer> list = new ArrayList<>(); 4 int[] a = new int[26]; 5 for ( int i = 0 ; i < S.length() ; i ++ ) 6 a[S.charAt(i)-‘a‘] = i; 7 8 int left = 0, right = 0, cur = 0; 9 while ( cur < S.length() ){10 char c = S.charAt(cur);11 right = Math.max(right,a[c-‘a‘]);12 if ( cur == right ){13 list.add(right-left+1);14 left = right+1;15 }16 cur++;17 }18 return list;19 }20 }
已耗用時間12ms,擊敗52.83%。已經儘力了。。
總結:關鍵在於想到map中儲存每個字元最後出現的次數,並且在迴圈過程中如何判斷是否滿足分區條件。
[leetcode] Partition Labels