leetcode 763 : 划分字母区间
字符串 S
由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
示例:
输入:S = "ababcbacadefegdehijhklij" 输出:[9,7,8] 解释: 划分结果为 "ababcbaca", "defegde", "hijhklij"。 每个字母最多出现在一个片段中。 像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。
提示:
-
S
的长度在[1, 500]
之间。 -
S
只包含小写字母'a'
到'z'
。
Related Topics
贪心
哈希表
双指针字符串
思路 1:
-
第一步,先把每一个字符的最大值保存到hashmap中。
-
第二步,每遍历一个字符,跟这个区间的内部的最大下标比较,直到将这个区间内的字符找完为止。
public List<Integer> partitionLabels(String s) { HashMap<Character,Integer> map = new HashMap<>(); ArrayList<Integer> result = new ArrayList<>(); //保持每一个字母的最大下标 for(int i = 0 ; i < s.length();i++){ map.put(s.charAt(i),i); } //因为map里面存储的是最大下标 //每遍历一个字符 都更新这个最大值 保证同一个字母出现在同一个区间 int start = 0; int end = 0; for(int i = 0; i < s.length();i++){ end = Math.max(end,map.get(s.charAt(i))); if(i == end){ //说明这个区间内已经计算完毕 result.add(end - start + 1); end++; start = end; } } return result; } 解答成功: 执行耗时:8 ms,击败了19.79% 的Java用户 内存消耗:41.1 MB,击败了5.02% 的Java用户
思路2 :
由于只有小写字符,使用hashmap的话,存取计算哈希值,效率不如直接使用一个长度26的数组。
public List<Integer> partitionLabels(String s) { int[] indexs = new int[26]; ArrayList<Integer> result = new ArrayList<>(); //保持每一个字母的最大下标 //int length = s.length(); for(int i = 0 ; i <s.length();i++){ indexs[s.charAt(i) - 'a'] = i; } //因为map里面存储的是最大下标 //每遍历一个字符 都更新这个最大值 保证同一个字母出现在同一个区间 int start = 0; int end = 0; for(int i = 0; i < s.length();i++){ end = Math.max(end,indexs[s.charAt(i)-'a']); if(i == end){ //说明这个区间内已经计算完毕 result.add(end - start + 1); end++; start = end; } } return result; } 执行耗时:4 ms,击败了56.85% 的Java用户 内存消耗:40.2 MB,击败了5.02% 的Java用户
思路3:
将s.length() 换成length时间效率有些许提高。
public List<Integer> partitionLabels(String s) { int[] indexs = new int[26]; ArrayList<Integer> result = new ArrayList<>(); //保持每一个字母的最大下标 int length = s.length(); for(int i = 0 ; i <length;i++){ indexs[s.charAt(i) - 'a'] = i; } //因为map里面存储的是最大下标 //每遍历一个字符 都更新这个最大值 保证同一个字母出现在同一个区间 int start = 0; int end = 0; for(int i = 0; i < length;i++){ end = Math.max(end,indexs[s.charAt(i)-'a']); if(i == end){ //说明这个区间内已经计算完毕 result.add(end - start + 1); end++; start = end; } } return result; } 解答成功: 执行耗时:2 ms,击败了98.98% 的Java用户 内存消耗:39.8 MB,击败了5.02% 的Java用户
思路4:
leetcode评论区看到,找到每一个字母的区间范围,这个题就变成合并区间范围这个题(第56题)。
但这个思路时间复杂度应该挺高的。 但想法确实不错。