双指针算法在实际开发中的具体应用之代码Review文章字符串的片段分割

本文是笔者在实际中具体遇到的场景,从中提取具体的核心的部分,使用前后指针进行性能优化的具体案例

开发需求场景

  • 前段时间,笔者在做代码Review的时候,发现了一个需求的前端实现方案不太优雅
  • 组员选择使用了循环加切割的方案去处理这个字符串
  • 笔者最终将其改为,使用快慢指针的方式,让其变得更加优雅,性能更佳

需求描述

  • 后端有一个字段返回一篇中文文章的具体内容
  • 比如有一个artical文章字段的值是一个长长的字符串
  • 需求抽象成:let artical = '白日依山尽,黄河入海流。欲穷千里目,更上一层楼。'
  • 前端展示的时候,需要一行一行展示(标点符号分隔,一句话就是一行)
  • 比如上述的artical的值,最终会展示成
html 复制代码
<p>白日依山尽</p>
<p>黄河入海流</p>
<p>欲穷千里目</p>
<p>更上一层楼</p>

循环加切割的方案

他的实现思路是:

先第一遍遍历,把原来的字符串"拷贝"一份,如果遇到了标点符号,统一使用横杠替换,最后再以横杠为标识,将字符串切割成数组,从而完成需求

实际上的标点符号,除了逗号、句号之外,还有问号,感叹号,省略号等,这里是为了更便于理解,抽象成为简单模型

代码

js 复制代码
let artical = '白日依山尽,黄河入海流。欲穷千里目,更上一层楼。'

function toArr(str) {
    let s = [',', '。']
    let ns = ''
    for (let i = 0; i < str.length - 1; i++) {
        if (s.includes(str[i])) {
            ns = ns + '-'
        } else {
            ns = ns + str[i]
        }
    }
    return ns.split('-')
}

const result = toArr(artical)
console.log('result', result)

点评

  • 首先,时间复杂度高,每次拼接都会复制整个已有字符串,字符串越长,复制的成本越高,累积起来甚至达到平方级的耗时。而artical字段的值,也不小,所以这种拼接方式效率不太高
  • 然后,有依赖特殊字符风险,若原字符串中本身包含 -,那么split('-') 则是会错误分割,尴尬了

快慢双指针方案

实现思路是

  • 定义两个指针lr,初始都在起点索引为0的地方
  • 使用while循环,让第一个指针r先往右跑
  • r遇到标点符号的时候,截取lr的区间的字符串存到数组里面
  • 而后,再让l赶上rr再往右跑,直到跑到头,跑完整个article字符串
  • 有点像,张三和李四拿着卷尺丈量操场的长度
  • 李四原地不动,张三拉着卷尺到头,记录一段距离
  • 李四再跑到张三的位置,张三再往前跑同时把卷尺拉到头
  • 如下动画:

代码

js 复制代码
let artical = '白日依山尽,黄河入海流。欲穷千里目,更上一层楼。'

function toArr(str) {
    let s = [',', '。']
    let arr = []
    let l = 0
    let r = 0
    while (r <= str.length - 1) {
        if (s.includes(str[r])) {
            let range = str.slice(l, r)
            arr.push(range)
            r = r + 1
            l = r
        } else {
            r = r + 1
        }
    }
    return arr
}
const result = toArr(artical)
console.log('result', result)

最终使用Set集合去判断是否是标点符号,即

js 复制代码
function toArr(str) {
    let s = new Set([',', '。'])
    let arr = []
    let l = 0
    let r = 0
    while (r <= str.length - 1) {
        if (s.has(str[r])) {
            let range = str.slice(l, r)
            arr.push(range)
            r = r + 1
            l = r
        } else {
            r = r + 1
        }
    }
    return arr
}

点评

  • 时间复杂度整体保持O(n)------n 为字符串长度【从头到尾跑一遍就行了】
  • 空间复杂度没大的开销
  • Set的语义更贴合 "判断元素是否在一个集合中" 的场景,代码清晰------Set天然用于去重和成员判断
  • 数组includes的效率会随标点符号数量增多而下降

A good memory is better than a bad pen. Record it down... 最后,再来回顾一下双指针的相关知识

双指针知识回顾

  • 双指针是相对于单指针而言的,我们常见的for循环和forEach只有一个索引变量i的,就是单指针,有两个变量,比如i或者j的,就是双指针
  • 双指针的本质是多定义一个索引变量j,用空间换时间提升效率的方式
  • 双指针分为快慢指针和对撞指针
    • 快慢指针------两个指针同侧出发移动,一前一后,一快一慢
    • 对撞指针------两个指针从两端向中间移动

快慢指针应用场景

  • 链表操作(判断循环、找中间节点)
  • 数组去重、字符串处理(本文就是一个具体实际应用)
  • DOM 树遍历等

对撞指针应用场景

  • 回文字符串验证
  • 有序数组的两数之和
  • 数组元素交换等
相关推荐
DuHz3 小时前
用于汽车雷达应用的步进频率PMCW波形——论文阅读
论文阅读·算法·汽车·信息与通信·信号处理·毫米波雷达
张晓~183399481213 小时前
碰一碰发抖音源码技术搭建部署方案
线性代数·算法·microsoft·矩阵·html5
weixin_448119943 小时前
Datawhale人工智能的数学基础 202510第3次作业
人工智能·算法
CoovallyAIHub3 小时前
全球OCR新标杆!百度0.9B小模型斩获四项SOTA,读懂复杂文档像人一样自然
深度学习·算法·计算机视觉
weixin_377634843 小时前
【强化学习】RLMT强制 CoT提升训练效果
人工智能·算法·机器学习
拾光Ծ3 小时前
【C++高阶数据结构】红黑树
数据结构·算法
Qiuner4 小时前
《掰开揉碎讲编程-长篇》重生之哈希表易如放掌
数据结构·算法·leetcode·力扣·哈希算法·哈希·一文读懂
cici158744 小时前
基于MATLAB的ADS-B接收机卫星与接收天线初始化实现
算法·matlab
木井巳4 小时前
[Java数据结构与算法]详解排序算法
java·数据结构·算法·排序算法