当前位置: 首页 > news >正文

贪心算法 | 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"));}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Docker-Compose配置zookeeper+KaFka+CMAK简单集群
  • Redisson中RQueue的使用场景附一个异步的例子
  • 基于vue-grid-layout插件(vue版本)实现增删改查/拖拽自动排序等功能(已验证、可正常运行)
  • Ubuntu24.04 deb文件 安装 MySQL8.4
  • GraphRAG + GPT-4o mini 低成本构建 AI 图谱知识库
  • 配置mysql8.0.21版本docker-compose启动容器
  • 星环科技携手东华软件推出一表通报送联合解决方案
  • mac大文件清理软件哪个好 mac大文件怎么清理 苹果电脑清理软件推荐免费
  • 深度学习复盘与论文复现E
  • 接口三层架构
  • 一些和颜色相关网站
  • 生成树协议配置与分析
  • 哪种SSL证书可以快速签发保护http安全访问?
  • springcloud-config客户端启用服务发现报错找不到bean EurekaHttpClient
  • 【打工日常】使用Prometheus+Grafana+Alertmanager+Webhook-dingtalk搭建监控平台
  • [case10]使用RSQL实现端到端的动态查询
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • Docker: 容器互访的三种方式
  • JavaScript的使用你知道几种?(上)
  • js学习笔记
  • Kibana配置logstash,报表一体化
  • leetcode388. Longest Absolute File Path
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • Rancher如何对接Ceph-RBD块存储
  • 编写符合Python风格的对象
  • - 概述 - 《设计模式(极简c++版)》
  • 简单数学运算程序(不定期更新)
  • 利用jquery编写加法运算验证码
  • 聊聊directory traversal attack
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 前端之React实战:创建跨平台的项目架构
  • 如何编写一个可升级的智能合约
  • 思否第一天
  • 交换综合实验一
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​如何在iOS手机上查看应用日志
  • #QT(智能家居界面-界面切换)
  • #我与Java虚拟机的故事#连载19:等我技术变强了,我会去看你的 ​
  • (24)(24.1) FPV和仿真的机载OSD(三)
  • (八十八)VFL语言初步 - 实现布局
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (亲测有效)推荐2024最新的免费漫画软件app,无广告,聚合全网资源!
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .Net Redis的秒杀Dome和异步执行
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET 依赖注入和配置系统
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NET单元测试
  • .net开发时的诡异问题,button的onclick事件无效
  • .Net转Java自学之路—SpringMVC框架篇六(异常处理)