JavaScript刷LeetCode-字符串类解题技巧

news2024/11/26 14:40:57

序章

我们把字符串数组正则排序递归归为简单算法。接下来系列里,将系列文章里将为大家逐一介绍。

字符串

翻转字符串中的单词

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例 1:
输入: "Let's take LeetCode contest"
输出: "s'teL ekat edoCteeL tsetnoc"
注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii

解题思路:要保证单词和空格的初始顺序;a)保证单词的先后顺序不能改变;b)保证单词的反转。

步骤一:先把句子分隔开,分割开后塞入数组里,数组的先后顺序就是单词的先后顺序。
步骤二:然后把数组的每个单词进行反转。

/** * @param {string} s
 * @return {string} */
var reverseWords = function(s) {
    let arr = s.split(' ')
    let result = arr.map(item=>{
        return item.split('').reverse().join('')
    })
   return  result.join(' ')
};

代码不够简洁,做下面处理。

var reverseWords = function(s) {
   return  s.split(' ').map(item => item.split('').reverse().join('')
   ).join(' ')
};

也可以把空格换成正则去处理,\s表示空格的意思。这里注意掌握split的2种用法。

var reverseWords = function(s) {
   return  s.split(/\s/g).map(item => item.split('').reverse().join('')
   ).join(' ')
};

还可以这么写。正则/[\w’]+/g就是识别单词的意思,中括号表示可选项,w是字符的意思,[\w’]表示可选字符和’, 不止一个元素,后面有个+号。
注意:这不是一个比较好的解法,如果单词中包含逗号,圆括号等,正则尾部会匹配到,输出的答案就会不理想。

var reverseWords = function(s) {
   return  s.match(/[\w']+/g).map(item => item.split('').reverse().join('')
   ).join(' ')
};

在这里插入图片描述

小结:本题涉及到的知识点如下所示。

String.prototype.split
String.prototype.match
Array.prototype.map
Array.prototype.reverse
Array.prototype.join

计数二进制子串

给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。  
重复出现的子串要计算它们出现的次数。

示例 1 :
输入: "00110011"
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。

请注意,一些重复出现的子串要计算它们出现的次数。

另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。

示例 2 :
输入: "10101"
输出: 4
解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。
注意:

s.length 在1到50,000之间。
s 只包含“0”或“1”字符。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-binary-substrings

这种难度大的题目,先找出输入输出的规律,并且实现。
如何找到规律呢?发现输入和输出的关系,寻找突破点。

解法一

步骤一:先把关系图谱展现出来,查找其中的规律。

  • 起始点在一次次的往右移
  • 从0开始查找0011,找到后就停止了,然后从下一位开始查找
  • 找到一个结果向下一位,并且把从下一位到最后一位这个子串作为下一次输入(新的输入,子输入)=》递归
  • 引入新概念:重复找过程。重复找子串的过程:找子串这个行为可以抽出来,作为一个公共的行为。

参考视频:传送门

在这里插入图片描述

步骤二:伪代码实现

  • 为啥i<str.length-1,因为如果光标在最后一位i=str.length-1,肯定不满足题目的0和1的非空(连续)条件,只剩下1位了
  • r=match(str.slice(i))找符合条件的子串
  • 找到满足条件的子串,就保存结果
for i=0;i<str.length-1;i++
    r=match(str.slice(i))
    if r
        result.push(r)

步骤三:计算子串代码演示
代码思路整理:

  • 利用for循环,将字符串从第一个开始传入match函数中,在match函数中使用正则表达式获取到字符串开头的字符(或是多个0或是多个1)
  • 再使用repeat方法,将开头获取到的多个0或1利用异或运算反转重复相同次数(举个例子:获取到了‘00’,那么反转之后就是‘11’)
  • 然后再建立一个正则表达式,将获取到的字符和反转后的字符拼接,使用test方法与传入的字符串进行比对,返回第一个比对成功的字符串,保存到数组result中
  • 以此类推,剃掉原字符串的第一个字符后再调用一次match方法,直到原字符串只剩下1个字符,返回数组result的长度
/** * @param {string} str
 * @return {number} */
var countBinarySubstrings = function(str) {
    let resultArr = [];
    let match = (str) => {
        let beforeStr = str.match(/^(0+|1+)/)[0]
        let afterStr = (beforeStr[0]^1).toString().repeat(beforeStr.length)
        let reg = new RegExp(`^(${beforeStr}${afterStr})`)
        if(reg.test(str)){
            return RegExp.$1
        } else {
            return ''
        }
    }
    for(i=0;len=str.length-1,i<len;i++) {
        let subStr = match(str.slice(i));
        if(subStr) {
            resultArr.push(subStr)
        } 
    }
    return resultArr.length
};

上述解题方法对于字符串比较长的场景通不过,只能跑通85个,还有5个测试用例跑不通。
小结:上述做法涉及到的知识点如下所示。

String.prototype.slice
String.prototype.match
Array.prototype.repeat
Array.prototype.push
RegExp

解法二

代码思路整理:

  • cur 与 pre分别记录当前数字连续出现的次数(例如:000或者11)与前一个数字连续出现的次数,result 结果子串的个数。
  • 判断当前数字是否与后一个数字相同。相同,则当前数字出现的次数cur加1。不同,则当前数字事实上变成了前一个数字,当前数字的次数重置为1。
  • 前一个数字出现的次数>=后一个数字出现的次数,则一定包含满足条件的子串。即cur小于等于pre则符合条件。
/**
 * @param {string} s
 * @return {number}
 */
var countBinarySubstrings = function(s) {
    let pre = 0, cur = 1, count = 0
    for (let i = 0, len = s.length - 1; i < len; i++) {

        if (s[i] === s[i+1]) {
            cur++ 
        } else {
            pre = cur
            cur = 1
        }
        if (pre >= cur) { 
            count++
        }
    }
    return count
};

解法三

代码思路整理:
计算连续的0或者1的长度。例如“0011100001”, 则为 (2,3,4,1), 只需计算相邻的两个元素的最小值,因为要求0和1必须在子串中连续。 即sum(2 min 3, 3 min 4, 4 min 1)

字符串用连续0或1的个数表示子串个数
001100112222min(2, 2) + min(2, 2) + min(2, 2) = 6
001100221min(2, 2) + min(2, 1) = 3
const countBinarySubstrings = function(s) {
 let count = 0,len=s.length-1,resultArr = [];
 for (i=0;i<=len;i++) {
     count ++ ;
     if(s[i]!==s[i+1]) {
        resultArr.push(count);
        count = 0;
     } 
 }
    let sum=0;
    for(i=0,len=resultArr.length-1;i<len;i++) {
        sum += Math.min(resultArr[i],resultArr[i+1])
    }
    return sum;
}

总结

  • 解法1是一个很直接很暴力的解法,但是对于ES6的基础知识要求比较高,用到slice、match、repeat等方法以及正则表达式。 但是由于解法1过于简单暴力,在正则表达式与原字符串进行比对时花费了大量的时间,尤其是原字符串非常长的时候,因此解法1并不是好的算法。
  • 解法2和3更加符合解题逻辑,同时解法2和3省去了与原字符串比对的过程,因此解法2和3在时间复杂度上面远比解法1优秀,。

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

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

相关文章

数据库和SQL介绍

数据库管理系统&#xff08;数据库软件)那么如何实现这种数据库形式的数据管理呢?我们需要借助:数据库管理系统&#xff0c;也就是常说的数据库软件。数据库软件是非常多的&#xff0c;常见的有:这些软件都能实现︰管理库﹑管理表、基于表来管理数据数据库和SQL的关系数据库是…

Java 诊断利器 Arthas 快速入门

Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&#xff0c;监测方法执行耗时&#xff0c;类加载信…

ORB-SLAM2 --- LocalMapping::KeyFrameCulling函数

目录 1.函数作用 2.code 3.函数解析 1.函数作用 检测当前关键帧在共视图中的关键帧&#xff0c;根据地图点在共视图中的冗余程度剔除该共视关键帧。 冗余关键帧的判定&#xff1a;90%以上的地图点能被其他关键帧&#xff08;至少3个&#xff09;观测到。 2.code /*** brie…

第七次作业部分

文章目录1、获取根分区剩余大小2、获取当前机器ip地址3、统计出apache的access.log中访问量最多的5个IP4、打印/etc/passwd中UID大于500的用户名和uid5、/etc/passwd 中匹配包含root或net或ucp的任意行6、处理以下文件内容,将域名取出并根据域名进行计数排序处理(百度搜狐面试题…

透过现象看本质,我找到了Netty粘包与半包的这几种解决方案。

1、粘包与半包 啥也不说了&#xff0c;直接上代码是不是有点不太友好&#xff0c;我所谓了&#xff0c;都快过年了&#xff0c;还要啥自行车 我上来就是一段代码猛如虎 1.1 服务器代码 public class StudyServer {static final Logger log LoggerFactory.getLogger(StudyS…

ORB-SLAM2 --- ORBmatcher::Fuse函数 --- 局部建图线程调用重载版

目录 1.函数作用 2.code 3.函数解析 1.函数作用 将参数一的关键帧的地图点与参数二的地图点集合进行融合。 将地图点投影到关键帧中进行匹配和融合&#xff1b;融合策略如下&#xff1a; 1.如果地图点能匹配关键帧的特征点&#xff0c;并且该点有对应的地图点&…

六、k8s Pod控制器详解

1 Pod控制器介绍 Pod是kubernetes的最小管理单元&#xff0c;在kubernetes中&#xff0c;按照pod的创建方式可以将其分为两类&#xff1a; 自主式pod&#xff1a;kubernetes直接创建出来的Pod&#xff0c;这种pod删除后就没有了&#xff0c;也不会重建控制器创建的pod&#x…

异常处理部分

文章目录一、异常概述及体系结构分类ErrorException异常的体系结构异常处理&#xff1a;抓抛模型异常处理机制一&#xff1a;try-catch-finallyfinally的使用异常处理机制一&#xff1a;throws异常类型如何选择两种方式手动生成异常对象如何定义自定义的异常类一、异常概述及体…

JVM学习- - -虚拟机栈详解

前言&#xff1a;今天学长带领大家走进JVM学习&#xff0c;让我们一起来学习认识虚拟机栈吧~ 目录 1 虚拟机栈概述 虚拟机栈出现的背景 初步印象 内存中的栈和堆 虚拟机栈基本内容 栈的优点 2 栈的存储单位 栈中存储什么&#xff1f; 栈运行原理 栈帧的内部结构 3 局…

【云原生】k8s之存储卷

内容预知 前言 1.emptyDir存储卷 2.hostPath存储卷 3.nfs共享存储卷 4. PVC 和 PV的静态存储卷 4.1 pv和pvc的介绍 4.2 pvc 和pv的创建过程及销毁过程 4.3 对pv的操作指导 4.4 静态创建pv和pvc资源由pod运用过程 步骤一&#xff1a;在NFS主机上创建共享目录&#xff0c;…

采用rknn-toolkit导出rknn模型并部署在rock3a-rk3568芯片 上全流程

因工作需要&#xff0c;需要将目标检测模型 部署在开发板上。在走了很多弯路后 找到一个成功的案例并记载下来 这里说一下我现有的硬件设备 。 我是购买的RADXA的rock3a开发板 搭载的soc是rk3568 这是开发板的正面图&#xff0c;因为瑞芯微针对计算机视觉中的目标检测模型有一…

Java IO流 - 缓冲流的详细使用介绍

文章目录缓冲流缓冲流概述字节缓冲流字符缓存流缓冲流 缓冲流概述 缓冲流介绍: 缓冲流也称为高效流、或者高级流。之前学习的字节流和字符流可以称为原始流。 作用&#xff1a;缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能 缓冲流分为: 字节缓存输入流、字节…

做个测试工具

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

uniapp中引入vant Weapp

Vant Weapp官&#xff1a;https://vant-contrib.gitee.io/vant-weapp/#/home 步骤一&#xff1a;下载vant组件插件 从github上下载该插件https://github.com/youzan/vant-weapp 只要这个dist文件夹&#xff0c;把dist重命名为vant&#xff1b; 步骤二&#xff1a; 与pages…

301-295- 至少有 K 个重复字符的最长子串-0105

题解 本题使用分治策略,如果某个字符的出现次数小于k,则用它将数组分开,再把每个子数组组委参数递归执行.如果都大于k,则将该字符串的长度返回. 用一个字符分割,往深了分割各子字符串,这个字符分割完成,使用另一个字符进行分割,而不是一次用多个字符进行分割.这个题递归有些绕…

电脑怎么重装系统?小白也能轻松掌握这些方法

重新安装计算机系统有两种原因&#xff1a;一种是计算机系统可以正常使用&#xff0c;但是电脑比较卡&#xff0c;为了提高它的运行速度&#xff0c;所以想要通过重新安装系统来解决这个问题&#xff1b;另一种原因是计算机系统文件丢失&#xff0c;系统出现蓝屏&#xff0c;或…

MQ概念简介

队列管理器 队列管理器是MQ系统中最上层的一个概念&#xff0c;由它为我们提供基于队列的消息服务。 2) 消息 在MQ中&#xff0c;我们把应用程序交由MQ传输的数据定义为消息&#xff0c;我们可以定义消息的内容并对消息进行广义的理解&#xff0c;比如&#xff1a;用户的各种类…

机器学习100天(二十九):029 K折交叉验证

机器学习100天,今天讲的是:K 折交叉验证! 《机器学习100天》完整目录:目录 机器学习中,我们常会遇到一个问题,就是超参数的选择,超参数就是机器学习算法中的调优参数,比如上一节 K 近邻算法中的 K 值。K 折交叉验证就是帮助我们选择最优的超参数。 首先,介绍一下简…

FPGA并行计算可编程芯片

玩转Zynq可以使用Vivado创建一个FPGA工程。什么是FPGA前言自FPGA诞生以来&#xff0c;FPGA&#xff08;现场可编程门阵列&#xff09;就引起了人们的关注。在1980年代中期&#xff0c;Ross Freeman和他的同事从Zilog购买了该技术&#xff0c;并创建了Xilinx&#xff0c;目标是A…

基于Java+SpringBoot+vue+node.js实现自行车租赁平台管理系统

基于JavaSpringBootvuenode.js实现自行车租赁平台管理系统 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目录基于JavaSp…