算法题:消除字符串中全部的b和连续的ac
最近碰到了一道面试题,虽然不难但是临试没想出好的解法,记录下来以作分享。
题目:消除字符串中全部的b和连续的ac
用例:
'aabbc' -> 'a''aaabbbccc' -> '''abcdcba' -> 'dca'
注意结合用例理解这个题目的意思,转化后的字符串中不能有任何b和连续的ac,而不是仅对初始值进行一次转换。
暴力法
既然最后得到的字符串中不能有任何b和连续的ac,那么我们可以很容易地想到使用正则连续地进行处理,直到处理前后的字符串相同,可以很容易地写出下面的代码:
function solution (str) {
const reg = /ac|b/g
let strCopy = str
do {
str = strCopy
strCopy = str.replace(reg, '')
} while (strCopy !== str)
return strCopy
}
但是暴力法显然不够好,它每次重复地去执行替换,对于aaaaaccccc这种字符串,需要执行5次。
那么有没有更好的方法呢?通过观察我们发现其实需要替换的字符序列必定符合{n个a}{m个b}{n个c}(m, n不都为0)这种格式。b我们可以先不去管它,先从格式开头的a入手。那么如果找到了a,怎么知道后面的字符序列中有没有c出现呢?而c出现的个数是否能跟a的个数匹配呢?我们可以先保存连续a的数量,然后如果后面出现了符合格式的c,则减少a的个数,直到a耗尽或者格式匹配失败。
存储a的解法
function solution(str) {
let countA = 0 // 连续a的个数
let result = ''
for (let i = 0; i < str.length; i++) {
if (str[i] === 'a') {
countA++
} else if (str[i] === 'b') {
continue
} else if (str[i] === 'c') {
if (countA === 0) {
result += 'c'
} else {
countA--
}
} else {
// 遇到其他字符,则保存的a需要释放
while (countA) {
result += 'a'
countA--
}
result += str[i]
}
}
// 最后需要释放所有保存的a
while (countA) {
result += 'a'
countA--
}
return result
}
存储a的解法有点类似于栈,遇到a入栈,遇到c出栈,遇到abc之外的字符排空栈。
这是一种时间复杂度O(n)的解法,但是在遇到类似aaaaaad这种字符串的时候,它还不够好,因为最后保存的a都要释放出来,有额外的时间开销。
双指针的解法
这是本题较好的一种解法,设两个指针cur和loc分别从头开始出发,cur每次移动一格,另一个指针loc保留当前的操作位置,如果cur指向的字符是c且loc指向的是a,则将loc回移一位(ac抵消了),如果遇到其他非b的字符,则将loc处的字符置为cur处的字符,一直进行直到到cur到达字符串尾部,此时取字符串开头到loc指针之间的子串即为本题的解。这种解法妙就妙在loc处的字符是即时更新的,一些边界条件都自动消除了。
画一个图更好理解一点,比如有字符串abeabcdaabbcg,它经过处理后应该得到aedag,下面是操作过程的图解:

这种方法在C++, Java中是可以实现in-place更新的,但Javascript字符串是不可变的,所以体现不出来。
function solution(str) {
let result = str.split('')
let location = -1
for (let i = 0; i < str.length; i++) {
let cur = str[i]
if (cur === 'c' && location >= 0 && result[location] === 'a') {
location --
} else if (cur !== 'b') {
result[++location] = cur
}
}
return result.slice(0, location + 1).join('')
}
最后做个技术总结,这道题难度不大,考察的是对字符串算法的理解,双指针、栈、动态规划等思想在字符串算法问题中还是有很多应用的,还是要通过学习去总结归纳。
算法题:消除字符串中全部的b和连续的ac的更多相关文章
- 实现一个算法,寻找字符串中出现次数最少的、并且首次出现位置最前的字符 如"cbaacfdeaebb",符合要求的是"f",因为他只出现了一次(次数最少)。并且比其他只出现一次的字符(如"d")首次出现的位置最靠前。
实现一个算法,寻找字符串中出现次数最少的.并且首次出现位置最前的字符如"cbaacfdeaebb",符合要求的是"f",因为他只出现了一次(次数最少).并且比其 ...
- [经典算法题]寻找数组中第K大的数的方法总结
[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...
- 前端与算法 leetcode 387. 字符串中的第一个唯一字符
目录 # 前端与算法 leetcode 387. 字符串中的第一个唯一字符 题目描述 概要 提示 解析 解法一:双循环 解法二:Set法单循环 算法 传入测试用例的运行结果 执行结果 GitHub仓库 ...
- C语言:判断t所指字符串中的字母是否由连续递增字母组成。-判断一个输入的任何整数n,是否等于某个连续正整数序列之和。-将一副扑克牌编号为1到54,以某种方式洗牌,这种方式是将这副牌分成两半,然后将他们交叉,并始终保持编号1的牌在最上方。
//判断t所指字符串中的字母是否由连续递增字母组成. #include <stdio.h> #include <string.h> void NONO(); int fun( ...
- 第5题 查找字符串中的最长回文字符串---Manacher算法
转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一 ...
- IT公司100题-25-求字符串中的最长数字串
问题描述: 实现一个函数,求出字符串中的连续最长数字串.例如输入”12345cbf3456″,输出”12345″. 函数原型为: void conti_num_max( const char * sr ...
- 《剑指offer》第五十题(字符串中第一个只出现一次的字符)
// 面试题50(一):字符串中第一个只出现一次的字符 // 题目:在字符串中找出第一个只出现一次的字符.如输入"abaccdeff",则输出 // 'b'. #include & ...
- Java入门:基础算法之从字符串中找到重复的字符
本程序演示从一个字符串中找出重复的字符,并显示重复字符的个数. import java.util.HashMap; import java.util.Map; import java.util.Set ...
- 【leetcode 简单】 第八十三题 反转字符串中的元音字母
编写一个函数,以字符串作为输入,反转该字符串中的元音字母. 示例 1: 输入: "hello" 输出: "holle" 示例 2: 输入: "leet ...
- (算法)判断字符串中是否包含HelloWorld
题目: 给定某字符串,判断该字符串中是否包含HelloWorld,出现HelloWorld不一定要连续,但顺序不变,如“HeByello,ByeWorByeld”就包含“HelloWorld”. 思路 ...
随机推荐
- 26 docker 安装 solr
准备一台已经安装过docker的服务器 获得solr镜像 #可以指定版本 docker pull solr:7.5.0docker pull solr:7.7.3 创建数据挂载文件夹 允许访问权限 s ...
- ASP.NET中maxRequestLength和maxAllowedContentLength的区别;上传大文件设置IIS7文件上传的最大大小
https://blog.csdn.net/qq_23663693/article/details/89920039 maxRequestLength表示ASP支持的最大请求大小,而maxAllowe ...
- JS脱敏姓名、身份证、电话、邮箱
一.姓名脱敏 handleName(name) { let arr = Array.from(name) let result = '' if (arr.length === 2) { result ...
- SDM
SDM:sigma delta Modulator SC:switch capacitor(开关电容) sigma delta调制器的分类 •单环路和级联(cascade)SDM:在于使用的量化器的数 ...
- git 问题解决
1. fatal: the remote end hung up unexpectedly git config --global http.postBuffer 104857600 其他方案: gi ...
- scrapy中发送post请求
1.可以使用`yield scrapy.FormRequest(url,formdata,callback)`方法发送POST请求. 其中构造参数formdata可以是字典,也可以是可迭代的(key, ...
- AndroidStudio中的读取本地Gradle设置,gradle-wrapper.properties内容解释
gradle-wrapper.properties文件长成下面这个样子 distributionBase=GRADLE_USER_HOMEdistributionPath=wrapper/distsd ...
- 一个新App上线应该注意什么?
一个新App上线应该关注哪些地方: 功能使用上无大问题遗留 用户使用体验尚佳 (前两条属于普通app更新也需要关注的点) 用户需要有反馈的入口,比如app内的反馈.用户可以直接联系到对应负责人进行反馈 ...
- android kotlin data class的公共参数解决
kotlin的 data class 不能简略的继承 另一个 data class(要初始化对应父类的值) 尝试使用 sealed class 解决 sealed class CommonParams ...
- Mongodb设置账号密码登录
Mongodb设置.首先设置Data目类和Log目录,然后新建mongodb.conf,设置内容大体如下 port = 27017 #数据目录 dbpath = /usr/softs/data/db ...