想要精通算法和SQL的成长之路 - 系列导航
原题链接
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。
示例:
看到这个题目,我先观察了一下示例的返回。试想一下,是根据什么来进行划分的?
如果下一个元素和当前元素不一致,就划分一个,那么结果就应该是: [“a”,“b”…]。那么肯定是不对的。
那么如果是下一个元素(i+1)以及下下个元素(i+2),都和当前元素不一致,就划分一个。貌似也不对:那么前几个应该是:[“aba”,“bcb”,“aca”…]。
到这里就能发现,从这个角度来思考肯定是走不通的,那么我们可以这么想:
首先:
那么我们可以用一个固定大小的数组,统计a-z中的所有字母,它在字符串中最后出现的位置是哪里。
int[] lastIndex = new int[27];
for (int i = 0; i < s.length(); i++) {lastIndex[s.charAt(i) - 'a'] = i;
}
遍历过程中,我们如何确定当前分割区间的右边界?
curMaxRight。i 和 curMaxRight 相等,就说明到达分割边界。left。找到分割边界的时候,左边界就好处理了,下一个左边界就是curMaxRight+1。// 记录左边界和右边界
int left = 0, curMaxRight = 0;
for (int i = 0; i < s.length(); i++) {// 当前这个字符对应的最原位置int lastIndex = lastIndexArr[s.charAt(i) - 'a'];// 遍历的同时,还要更新当前区间中重复出现的最远位置。curMaxRight = Math.max(curMaxRight, lastIndex);// 如果两者相等,说明当前位置就是边界值if (curMaxRight == i) {// 计入结果,计算当前区间的大小res.add(curMaxRight - left + 1);// 更新左边界left = i + 1;}
}
那么最终结果如下:
public List partitionLabels(String s) {ArrayList res = new ArrayList<>();int[] lastIndexArr = new int[27];for (int i = 0; i < s.length(); i++) {lastIndexArr[s.charAt(i) - 'a'] = i;}// 记录左边界和右边界int left = 0, curMaxRight = 0;for (int i = 0; i < s.length(); i++) {// 当前这个字符对应的最原位置int lastIndex = lastIndexArr[s.charAt(i) - 'a'];// 遍历的同时,还要更新当前区间中重复出现的最远位置。curMaxRight = Math.max(curMaxRight, lastIndex);// 如果两者相等,说明当前位置就是边界值if (curMaxRight == i) {// 计入结果,计算当前区间的大小res.add(curMaxRight - left + 1);// 更新左边界left = i + 1;}}return res;
}
上一篇:描写人物神态的句子
下一篇:在水上有男女老幼贫富贱猜一成语