[leetcode] Partition Labels
Posted Lin.B
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[leetcode] Partition Labels相关的知识,希望对你有一定的参考价值。
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.
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的主要内容,如果未能解决你的问题,请参考以下文章
*Leetcode 763. Partition Labels
LeetCode 663. Equal Tree Partition