欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 贪心算法 | 763.划分字母区间

贪心算法 | 763.划分字母区间

2025/9/16 13:22:50 来源:https://blog.csdn.net/weixin_57865902/article/details/140674164  浏览:    关键词:贪心算法 | 763.划分字母区间

·题目描述

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。

返回一个表示每个字符串片段的长度的列表。

示例 1:

输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。 

示例 2:

输入:s = "eccbbbbdec"
输出:[10]

·解题思路

很质朴的想法是,遍历一圈字符串s, 把每个字母出现的起始位置用数组记录下来。再套用之前leetcode 452 用最少数量的箭引爆气球  和 leetcode 435 无重复区间的 思路, 将数组进行规划;

规划分为三步:1.最开始的位置进行排序;2.当后一个数组的开始位置小于前一个数组的结束位置的时候,说明两个数组有重叠,更新数组区间;3.当后一个数组的开始位置大于前一个数组的结束位置的时候,说明两个数组没有重叠区间,需要计算前一个数组的字符串长度

·解题细节:

1.每一个字母都可能出现,因此创建26*2的二维数组,计算每一个出现的字母的开始和结束位置。同时,如何判断该数字是开始坐标还是结束坐标------创建flag数组来标记,若是flag = 0 ,表示之前没有出现过,该坐标为起始坐标,反之则为结束坐标。结束坐标需要不断更新;

            int[][] num = new int[26][2];int[] flag = new int[26];for(int i = 0; i < s.length(); i++){int temp  = s.charAt(i) - 'a';if(flag[temp] == 0){num[temp][0] = i;flag[temp] = 1;}else{ num[temp][1] = Math.max(num[temp][1], i);}}

2.对记录的字母坐标按照第一个元素进行排序

Arrays.sort(num, new Comparator<int[]>() {@Overridepublic int compare(int[] o1, int[] o2) {return Integer.compare(o1[0], o2[0]);}});#打印结果for(int i = 0; i < num.length; i++){System.out.println(num[i][0] + " " + num[i][1]);}

3.对坐标数组进行处理,遍历num数组,利用栈来辅助更新区间。当当前数组的开始位置小于栈顶数组的结束位置的时候,说明两个数组有重叠,更新数组区间;反之说明两个数组没有重叠区间,需要计算前一个数组的字符串长度

        Stack<int[]> stack = new Stack<int[]>();for(int i = 0;i < num.length;i++){#当栈为空的时候,先压入if(stack.isEmpty()) stack.push(num[i]);else{int[] point = stack.peek();if(num[i][0] < point[1]){int newend = Math.max(point[1], num[i][1]);int[] newpoint = new int[] {point[0],newend};stack.pop();stack.push(newpoint);}else{int len = stack.peek()[1] - stack.peek()[0] + 1;res.add(len);stack.pop();stack.push(num[i]);}}}

4.有可能最后一个子字符串不能满足for循环的收割条件,也就是说栈不为空,这是还需要处理

        while(!stack.isEmpty()){int[] point = stack.pop();if(point[1] == 0) {res.add(1);count += 1;}else{int len = point[1] - point[0] + 1;res.add(len);}}

5.处理空数组:

由于给出的字符不一定包含26个字母,也就是说num中有很多空数组参与了排序,这时候只需要在遍历的时候,当数组两个元素都是0的时候,continue即可

if(num[i][0] == 0 && num[i][1] == 0){continue;}

6.处理单个元素

字符串中可能存在单个元素,分为两种情况:头单个【0,0】和其他【x(x!= 0) , 0】

处理头单个的时候,只需要增加一个count技术,当所有子串的长度小于给定字符串的长度时,说明有头单个元素漏加,只需要在列表结构头部增加 1 ,即可

处理其他单个元素的时候,只需要在遍历num时,当数组第一个元素不为0,而第二元素为0 的时候,将第二个元素变为第一个元素相同值即可

            if(num[i][0] == 0 && num[i][1] == 0){continue;}if(num[i][0] != 0 &&  num[i][1] == 0){num[i][1] = num[i][0];}

·java代码

import java.util.*;class Solution {public List<Integer> partitionLabels(String s) {int[][] num = new int[26][2];int[] flag = new int[26];int count = 0;for(int i = 0; i < s.length(); i++){int temp  = s.charAt(i) - 'a';if(flag[temp] == 0){num[temp][0] = i;flag[temp] = 1;}else{ num[temp][1] = Math.max(num[temp][1], i);}}Arrays.sort(num, new Comparator<int[]>() {@Overridepublic int compare(int[] o1, int[] o2) {return Integer.compare(o1[0], o2[0]);}});for(int i = 0; i < num.length; i++){System.out.println(num[i][0] + " " + num[i][1]);}List<Integer> res = new ArrayList<Integer>();Stack<int[]> stack = new Stack<int[]>();for(int i = 0;i < num.length;i++){if(num[i][0] == 0 && num[i][1] == 0){continue;}if(num[i][0] != 0 &&  num[i][1] == 0){num[i][1] = num[i][0];}if(stack.isEmpty()) stack.push(num[i]);else{int[] point = stack.peek();if(num[i][0] < point[1]){int newend = Math.max(point[1], num[i][1]);int[] newpoint = new int[] {point[0],newend};stack.pop();stack.push(newpoint);}else{int len = stack.peek()[1] - stack.peek()[0] + 1;res.add(len);count += len;stack.pop();stack.push(num[i]);}}}while(!stack.isEmpty()){int[] point = stack.pop();if(point[1] == 0) {res.add(1);count += 1;}else{int len = point[1] - point[0] + 1;res.add(len);count += len;}}if(count < s.length()) res.add(0,1);return res;}
}public class Main {public static void main(String[] args) {Solution solution = new Solution();System.out.println(solution.partitionLabels("vhaagbqkaq"));}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词