统计字符串中出现最多的字母与个数

653 阅读2分钟

前言

技术群里发了一道字符串算法题,群里开始热闹起来了,刚好手里的需求提测了,闲着也是闲着,写写代码研究一下。

问题

统计字符串中出现最多的字母与个数?

var str = ‘wodexiaomaojiaoxiaohei’;

分析

  • 检验字符串 边界处理
  • 字符串转换为数组
  • 统计所有字母出现的次数

思路出来就开始迈开第一步,具体实现如下:

const str = "wodexiaomaojiaoxiaohei";

function mostTimes(str) {
    // 检验字符串格式
    if (typeof str !== 'string' || !str) {
        return
    }

    // 将字符串转换为数组
    const arr = str.split('')
    const obj = {}
    arr.forEach((item, index) => {
        if (obj[item]) {
            obj[item] = {
                times: Number(obj[item].times) + 1,
                first: obj[item].first,
                lastfirst: index
            }
        } else {
            obj[item] = {
                times: 1,
                first: index,
                lastfirst: index
            }
        }
    });
    console.log(obj)

    // 统计字符最多的字母
    // 首先统计各个字母的字数
    let tempArr = []
    for (const i in obj) {
        tempArr.push(obj[i].times)
    }

    // 对次数排序
    tempArr.sort()

    // 字母最多的次数
    const maxTimes = tempArr[tempArr.length - 1]
    let el = ''
    for (const i in obj) {
        if (obj[i].times == maxTimes) {
            // 次数最多的字母
            el = i
        }
    }

    console.log(el, maxTimes)
}

mostTimes(str)

运行结果如图所示:

这个方案进行了最笨的数组遍历,两次对象遍历,可以说性能有点差,不过这种方案,在处理的时候方便汇总其它的信息,比如出现次数最后的字母首次出现的位置、最后一次出现的位置。

不过怎么进行优化,让性能更好一些呢。思路优化和语法糖优化?我陷入了沉思.....

优化

  1. 优化一: 字符串符合迭代器规则,可以直接对字符串遍历,可以减少字符串到数组的转换操作。其次将字符串整合为对象的处理,可以使用 for in 语法糖
// const arr = str.split('') // 删除

const obj = {}
for(let i of str) {
    if (i in obj) {
        obj[i] ++
    } else {
        obj[i] = 1
    }
}

2)优化二: 拿到字母的次数数组,快速获取到数组中的最大值,目前的处理是先排序,在取值。🤦️,这里可以直接使用 Math.max()来处理,数字可以通过 ... 拉平。

// 对次数排序
// tempArr.sort()

// 字母最多的次数
// const maxTimes = tempArr[tempArr.length - 1]

const maxTimes = Math.max(...tempArr)

现在的实现如下:

const str = "wodexiaomaojiaoxiaohei";

function mostTimes(str) {
    // 检验字符串格式
    if (typeof str !== 'string') {
        return
    }

    const obj = {}
    for(let i of str) {
        if (i in obj) {
            obj[i] ++
        } else {
            obj[i] = 1
        }
    }

    console.log(obj)

    // 统计字符最多的字母
    // 首先统计各个字母的字数
    let tempArr = []
    for (const i in obj) {
        tempArr.push(obj[i])
    }

    // 字母最多的次数
    const maxTimes = Math.max(...tempArr)
    let el = ''
    for (const i in obj) {
        if (obj[i] == maxTimes) {
            // 次数最多的字母
            el = i
        }
    }

    console.log(el, maxTimes)
}

mostTimes(str)

运行结果如图所示:

总结

一道小题,从开始思考实现思路到能够自主发现问题,进行优化尝试和解决问题,这应该是作为一个技术开发的基本素质。这道逻辑题目还有很大的优化空间,后续会有时间会继续优化的。