算法随笔_30: 去除重复字母

上一篇:算法随笔_29:最大宽度坡_方法3-CSDN博客

=====

题目描述如下:

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

示例 1:

输入:s = "bcabc"
输出"abc"

=====

算法思路:

首先我们考虑第一个条件: 如何去掉字符串中重复的字母?这个比较简单。我们可以新开辟一个同样长度的新数组s_new来存储最后的结果。然后我们从左往右遍历原数组,依次把字符放入新数组s_new中。并判断即将放入的字符在新数组当中是否已经出现,如果出现,则不放入字符。最终得到的就是去掉重复字符之后的新的字符串。在代码实现的时候可能会有一些细节需要考虑,比如说,s_new数组后面可能会出现未填满的情况,但这属于细节问题,在代码实现中可以用各种办法解决它,同时也不会影响时间复杂度。

现在让我们来看第二个条件: 最终答案需要取字典序最小的字符串。比如,示例1中有两种可能的符合去重条件的答案: bca,  abc。同样都是去掉重复字符之后的字符串,但字典序最小的字符串是abc。

因此,在上面的算法中,当发现放入的字符比如: c,在新数组中已经出现时,我们需要一个算法来判断如何进行重复字符的取舍问题。是保留已经在数组中的字符c,还是需要删除它,放入后面的字符c。

我们拿上面的例子做进一步的分析。bcabc,我们从左向右枚举原字符串,当枚举到第二个b时,如果删除最后一个b,那么字符串就变成bca。删除第一个b,字符串就变成了cab。我们发现只要b的后面的字符是大于b的,肯定要删除第二次出现的重复字母。因为如果删除了第一次出现的字符b,字符c就前移一位,不管后面的字符串是什么样的,以字符c开始引领的字符串必然大于以字符b开始引领的同样长度的字符串。

与上面的情况类似,如果b的后面的字符是小于b的字符,那需要删除第一个字符b。比如bab,最后的结果应该是ab。

因此,我们发现的特征就是:

如果s[i]>s[i+1],且s[i]这个字符出现2次及以上时,我们需要删除这个字符s[i]。

此时注意一下,当删除s[i]之后,s[i+1]移到了s[i]这个位置,新的排列仍然需要保持这个特征。即,如果s[i-1]仍然大于s[i+1],且s[i-1]这个字符出现2次及以上时,我们仍需要删除这个字符s[i-1],s[i+1]需要继续前移。

还是用上面的例子说明,当我们尝试放入s_new时,有如下步骤:

- 放入b

- 因为c大于b,所以放入c

- 因为a小于c,且c出现2次,删除c

- a继续和b比较,a小于b,且b出现2次,删除b。前面已经没有可以删除的字符,放入a。

- 因为b大于a,所以放入b

- 因为c大于b,所以放入c,至此完成。

这里有一些细节还需要说明一下。

1. 假如原字符很长,abc后面还有其他字符,且abc每个字符后面都还出现多次以上。仍然需要按照上面的规律来放入s_new。

2.  只出现1次的字符,必须保留。比如上面的例子,如果没有第二次出现的字符c。需要依次放入bca,然后舍弃第二个b。因为字符c不能删除,所以字符a就无需依次和前面的比较了。

3.  即将放入的字符如果在s_new中已经存在,则不能放入。

我们发现s_new中的字符有个特点,除了那些只出现1次的字符,出现2次及以上的字符都是按字典序增大的,然后碰到小于的字符在一个一个删除。这很像一个的数据结构。先递增入栈,在依据条件出栈。

经过上面一系列的分析,我们大体了解了整个的算法思路。下面我们来给出详细的算法:

1. 初始ch2cnt数组,共26个元素。我们用每个字母与字母a的ascii码的差值来做为数组的索引。初始元素值为0。遍历一遍原字符串,相同字母每出现一次,ch2cnt相应的元素值加1。统计出每个字母出现的次数。

2.  初始putted数组,也是26个元素。用每个字母与字母a的ascii码的差值来做为数组的索引。元素值为1表示此字母在s_new中已经存在,0表示不存在。然后把原字符串s中第一个字符在putted中对应的元素置为1。设置此数组的目的是为了更高效的查询s_new中已存在的字符,仅有O(1) 的时间复杂度。

3. 设s_new数组为最终的字符串数组。初始化时放入原字符串s的第一个字符。

4.  从第二个字符开始,从左向右枚举原字符串s。

5.  通过putted,判断当前字符s[i]是否在s_new中已经存在。如果存在,不放入s_new,且在ch2cnt中对应字符的次数减1。转到步骤4继续。如果不存在,转到下一步。

5.  从右往左枚举s_new数组,让s[i]依次与s_new数组的字符j比较,如果s[i]<=s_new[j]且字符j出现的次数大于1,我们去掉s_new的最后一个字符。循环步骤5,直到退出循环,然后我们把s[i]放入s_new。

其他一些细节详见代码。下面是代码实现:

class Solution(object):def removeDuplicateLetters(self, s):""":type s: str:rtype: str"""ord_a=ord('a')ch2cnt=[]putted=[]for i in range(26):ch2cnt.append(0)putted.append(0)for ch in s:ch2cnt[ord(ch)-ord_a]+=1s_len=len(s)s_new=[s[0]]putted[ord(s[0])-ord_a]=1for i in range(1,s_len):ord_si=ord(s[i])-ord_aif putted[ord_si]==1:ch2cnt[ord_si]-=1continuej=len(s_new)-1while j>=0 and s[i]<=s_new[j] and ch2cnt[ord(s_new[j])-ord_a]>1:ch2cnt[ord(s_new[j])-ord_a]-=1putted[ord(s_new[j])-ord_a]=0s_new.pop()j-=1s_new.append(s[i])putted[ord_si]=1res=''.join(s_new)return res

此算法的时间复杂度为O(n) 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/68551.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue 3 30天精进之旅:Day 08 - 组件通信

在Vue 3的开发过程中&#xff0c;组件之间的通信是一个至关重要的概念。理解如何在父子组件、兄弟组件以及通过全局事件总线进行通信&#xff0c;将帮助我们构建更为灵活和可维护的应用。在今天的学习中&#xff0c;我们将探讨以下几个方面&#xff1a; 父子组件之间的通信兄弟…

【Hadoop】Hadoop 概述

Hadoop 概述 Hadoop 是什么Hadoop 发展历史Hadoop 三大发行版本Hadoop 优势&#xff08;4 高&#xff09;Hadoop 组成&#xff08;面试重点&#xff09;HDFS 架构概述YARN 架构概述MapReduce 架构概述HDFS、YARN、MapReduce 三者关系 大数据技术生态体系 Hadoop 是什么 Hadoop…

网络爬虫学习:应用selenium获取Edge浏览器版本号,自动下载对应版本msedgedriver,确保Edge浏览器顺利打开。

一、前言 我从24年11月份开始学习网络爬虫应用开发&#xff0c;经过2个来月的努力&#xff0c;于1月下旬完成了开发一款网络爬虫软件的学习目标。这里对本次学习及应用开发进行一下回顾总结。 前几天我已经发了一篇日志&#xff08;网络爬虫学习&#xff1a;应用selenium从搜…

关于使用微服务的注意要点总结

一、防止过度设计 微服务的拆分一定要结合团队人员规模来考虑&#xff0c;笔者就曾遇到过一个公司的项目&#xff0c;是从外部采购回来的&#xff0c;微服务划分为十几个应用&#xff0c;我们在此项目基础上进行自行维护和扩展。由于公司业务规模不大&#xff0c;而且二次开发的…

CSS Fonts(字体)

CSS Fonts(字体) 在网页设计中,字体是传达信息情感和风格的关键元素。CSS(层叠样式表)提供了丰富的字体样式和属性,使得网页设计者能够根据需求选择合适的字体,从而提升用户体验。本文将详细介绍CSS字体相关的知识,包括字体的选择、加载、样式设置等。 字体的选择 选…

week08_文本匹配任务

1、文本匹配任务概述 狭义&#xff1a; 给定一组文本&#xff0c;判断其是否语义相似 今天天气不错 match 今儿个天不错呀 √ 今天天气不错 match 你的代码有bug 以分值形式给出相似度 今天天气不错 match 今儿个天不错呀 0.9 今天天气不错 match…

Deepseek技术浅析(一)

DeepSeek 是北京深度求索人工智能基础技术研究有限公司推出的人工智能技术品牌&#xff0c;专注于大语言模型&#xff08;LLM&#xff09;的研发与应用。其技术涵盖了从模型架构、训练方法到应用部署的多个层面&#xff0c;展现出强大的创新能力和应用潜力。以下将详细介绍 Dee…

火出圈的DeepSeeK R1详解

各位宝子们,新年好! 模型特性 DeepSeek-R1是一款创新的AI推理模型,具有多项独特特性: 高性能推理能力 :在数学、代码和自然语言推理等任务上表现出色,性能对标OpenAI o1正式版。 强化学习驱动的训练 :采用大规模强化学习技术,仅需极少量标注数据,显著提升推理能力。…

Kafka 副本机制(包含AR、ISR、OSR、HW 和 LEO 介绍)

文章目录 Kafka 副本机制&#xff08;包含AR、ISR、OSR、HW 和 LEO 介绍&#xff09;1. 副本的基本概念2. 副本同步和一致性2.1 AR&#xff08;Assigned Replicas&#xff09;2.2 ISR&#xff08;In-Sync Replicas&#xff09;2.3 OSR&#xff08;Out-of-Sync Replicas&#xf…

【JavaEE】_MVC架构与三层架构

目录 1. MVC架构 2. 三层架构 3. MVC架构与三层架构的对比 3.1 MVC与三层架构的对比 3.2 MVC与三层架构的共性 1. MVC架构 在前文已介绍关于SpringMAC的设计模式&#xff0c;详见下文&#xff1a; 【JavaEE】_Spring Web MVC简介-CSDN博客文章浏览阅读967次&#xff0c;点…

CAPL与外部接口

CAPL与外部接口 目录 CAPL与外部接口1. 引言2. CAPL与C/C++交互2.1 CAPL与C/C++交互简介2.2 CAPL与C/C++交互实现3. CAPL与Python交互3.1 CAPL与Python交互简介3.2 CAPL与Python交互实现4. CAPL与MATLAB交互4.1 CAPL与MATLAB交互简介4.2 CAPL与MATLAB交互实现5. 案例说明5.1 案…

【Matlab高端绘图SCI绘图模板】第006期 对比绘柱状图 (只需替换数据)

1. 简介 柱状图作为科研论文中常用的实验结果对比图&#xff0c;本文采用了3组实验对比的效果展示图&#xff0c;代码已调试好&#xff0c;只需替换数据即可生成相关柱状图&#xff0c;为科研加分。通过获得Nature配色的柱状图&#xff0c;让你的论文看起来档次更高&#xff0…

随机森林例子

完整代码&#xff1a; # 导入必要的库 from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import numpy as np# 加载鸢尾花数…

【QT】 控件 -- 显示类

&#x1f525; 目录 [TOC]( &#x1f525; 目录) 1. 前言 2. 显示类控件2.1 Label 1、显示不同文本2、显示图片3、文本对齐、自动换行、缩进、边距4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 &#x1f525; 1. 前言 之前我在上一篇文章【QT】…

SpringBoot中@Valid与@Validated使用场景详解

SpringBoot中Valid与Validated使用场景详解 在实际开发中&#xff0c;参数校验是保证接口安全性和数据完整性的重要手段。Spring Boot提供了Valid和Validated两个核心注解来实现参数校验&#xff0c;但许多开发者对它们的区别和使用场景存在疑惑。本文将深入解析二者的差异&am…

基于PyQt设计的智能停车管理系统

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】设计意义【4】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】VSCODE【2】python【3】ptqt【4】HyperLPR31.5 参考文献二、安装Python环境1.1 环境介绍**1.2 Python版本介…

前端-Rollup

Rollup 是一个用于 JavaScript 的模块打包工具&#xff0c;它将小的代码片段编译成更大、更复杂的代码&#xff0c;例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式&#xff0c;而不是以前的 CommonJS 和 AMD 等特殊解决方案。ES 模块允许你自由…

数仓ETL测试

提取&#xff0c;转换和加载有助于组织使数据在不同的数据系统中可访问&#xff0c;有意义且可用。ETL工具是用于提取&#xff0c;转换和加载数据的软件。在当今数据驱动的世界中&#xff0c;无论大小如何&#xff0c;都会从各种组织&#xff0c;机器和小工具中生成大量数据。 …

策略模式 - 策略模式的使用

引言 在软件开发中&#xff0c;设计模式是解决常见问题的经典解决方案。策略模式&#xff08;Strategy Pattern&#xff09;是行为型设计模式之一&#xff0c;它允许在运行时选择算法的行为。通过将算法封装在独立的类中&#xff0c;策略模式使得算法可以独立于使用它的客户端…

网络直播时代的营销新策略:基于受众分析与开源AI智能名片2+1链动模式S2B2C商城小程序源码的探索

摘要&#xff1a;随着互联网技术的飞速发展&#xff0c;网络直播作为一种新兴的、极具影响力的媒体形式&#xff0c;正逐渐改变着人们的娱乐方式、消费习惯乃至社交模式。据中国互联网络信息中心数据显示&#xff0c;网络直播用户规模已达到3.25亿&#xff0c;占网民总数的45.8…