程序员面试金典面试题 01.06. 字符串压缩

简介: 程序员面试金典面试题 01.06. 字符串压缩

前言


本系列文章为《程序员面试金典》刷题笔记。

题目位置:字符串压缩

题集:程序员面试金典


题目


字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。


示例1:

 输入:"aabcccccaaa"
 输出:"a2b1c5a3"

示例2:

输入:"abbccd"
 输出:"abbccd"
 解释:"abbccd"压缩后为"a1b2c2d1",比原字符串长度更长。


提示:

字符串长度在[0, 50000]范围内。

思路


字符串长度也不算长,int还是能存下的,遇到这种题目怎么着也得遍历一遍。我最直接的思路就是定义变量来记数,先保存第一个字符,长度初始化为1。


count := 1
res :=string(S[0])


从第一个字符开始遍历

for i:=1;i<len(S);i++{
  ......


每次当前字符和前一个字符比较,只要和上一个不同就保存记录下来,然后计数器重置为1。


if S[i] == S[i-1]{
    count ++
}else{
    res = res + strconv.Itoa(count) + string(S[i])
    count = 1
 }

最后要注意边界,如果是字符串长度是0-2个长度的,压缩了也没有意义,直接返回了。

if len(S)<= 2{
        return S
    }


完整代码见下一节代码(优化前)

看结果:



aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS9jb2RpbmczbWluLzIwMjAtMDMtMTYtMTUxMzU2LmpwZw.png


天啊,内存消耗是小了,但是速度也太慢了。算法已经这么简化了,要优化速度只能从go语言的特性来了,大概率是追加字符串浪费了很多时间。


golang 里面的字符串都是不可变的,每次运算都会产生一个新的字符串,所以会产生很多临时的无用的字符串,不仅没有用,还会给 gc 带来额外的负担,所以性能比较差


这里引入到bytes.Buffer类型,可以当成可变字符使用,对内存的增长也有优化,如果能预估字符串的长度,还可以用 buffer.Grow()接口来设置 capacity(容量)


用法举例:

 var buffer bytes.Buffer
        buffer.WriteString(hello)
        buffer.WriteString(",")
        buffer.WriteString(world)
        _ = buffer.String()

代码见下一节,优化后。


aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS9jb2RpbmczbWluLzIwMjAtMDMtMTYtMTUyNDQ4LmpwZw.png


棒极了,写完提交github睡觉。

代码

优化

Go

func compressString(S string) string {
    if len(S)<= 2{
        return S
    }
    count := 1
    res :=string(S[0])
    for i:=1;i<len(S);i++{
        if S[i] == S[i-1]{
            count ++
        }else{
            res = res + strconv.Itoa(count) + string(S[i])
            count = 1
        }
    }
    res = res + strconv.Itoa(count)
    if len(res) < len(S){
        return res
    }else{
        return S
    }
}

优化后

Go

func compressString(S string) string {
    if len(S)<= 2{
        return S
    }
    count := 1
    var res bytes.Buffer
    res.WriteString(string(S[0]))
    for i:=1;i<len(S);i++{
        if S[i] == S[i-1]{
            count ++
        }else{
            res.WriteString(strconv.Itoa(count))
            res.WriteString(string(S[i]))
            count = 1
        }
    }
    res.WriteString( strconv.Itoa(count) )
    resStr := res.String()
    if len(resStr) < len(S){
        return resStr
    }else{
        return S
    }
}


相关文章
|
1月前
|
存储 NoSQL Redis
Redis常见面试题:ZSet底层数据结构,SDS、压缩列表ZipList、跳表SkipList
String类型底层数据结构,List类型全面解析,ZSet底层数据结构;简单动态字符串SDS、压缩列表ZipList、哈希表、跳表SkipList、整数数组IntSet
|
3月前
|
算法 程序员 Go
PHP 程序员学会了 Go 语言就能唬住面试官吗?
【9月更文挑战第8天】学会Go语言可提升PHP程序员的面试印象,但不足以 solely “唬住” 面试官。学习新语言能展现学习能力、拓宽技术视野,并增加就业机会。然而,实际项目经验、深入理解语言特性和综合能力更为关键。全面展示这些方面才能真正提升面试成功率。
59 10
|
4月前
|
安全 Java 编译器
【Java基础面试二十九】、说一说你对字符串拼接的理解
这篇文章讨论了Java中字符串拼接的四种常用方式(使用`+`运算符、`StringBuilder`、`StringBuffer`和`String`类的`concat`方法),每种方式适用的场景,以及在不同情况下的性能考量。
|
4月前
|
Java
【Java基础面试二十八】、使用字符串时,new和““推荐使用哪种方式?
这篇文章讨论了在Java中使用字符串时,推荐使用双引号`""`直接量方式而不是使用`new`操作符,因为`new`会在常量池之外额外创建一个对象,导致更多的内存占用。
|
4月前
|
JavaScript 前端开发 小程序
CoderGuide 程序员前后端面试题库,打造全网最高质量题库
CoderGuide涵盖范围包括且不限于:前端面试题(Vue,React,JS,HTTP,HTML,CSS面试题等),后端面试题(Java,Python,Golang,PHP,Linux,Mysql面试题等),以及算法面试题,大厂面试题,高频面试题,校招面试题等,你想要的,这里都有!
73 2
|
5月前
|
算法 Java
Java面试题:解释垃圾回收中的标记-清除、复制、标记-压缩算法的工作原理
Java面试题:解释垃圾回收中的标记-清除、复制、标记-压缩算法的工作原理
66 1
|
5月前
|
算法 Java 程序员
Java面试题:解释Java的垃圾回收机制,包括常见的垃圾回收算法。介绍一下Java的垃圾回收算法中的标记-压缩算法。
Java面试题:解释Java的垃圾回收机制,包括常见的垃圾回收算法。介绍一下Java的垃圾回收算法中的标记-压缩算法。
52 0
|
5月前
|
存储 安全 Java
Java面试题:请解释Java中的字符串和字符串缓冲区?
Java面试题:请解释Java中的字符串和字符串缓冲区?
36 0
|
5月前
|
存储 安全 Java
Java面试题:Java内存管理、多线程与并发框架:一道综合性面试题的深度解析,描述Java内存模型,并解释如何在应用中优化内存使用,阐述Java多线程的创建和管理方式,并讨论线程安全问题
Java面试题:Java内存管理、多线程与并发框架:一道综合性面试题的深度解析,描述Java内存模型,并解释如何在应用中优化内存使用,阐述Java多线程的创建和管理方式,并讨论线程安全问题
48 0
|
5月前
|
存储 并行计算 安全
Java面试题:Java内存管理、多线程与并发框架的面试题解析与知识点梳理,深入Java内存模型与垃圾回收机制,Java多线程机制与线程安全,Java并发工具包与框架的应用
Java面试题:Java内存管理、多线程与并发框架的面试题解析与知识点梳理,深入Java内存模型与垃圾回收机制,Java多线程机制与线程安全,Java并发工具包与框架的应用
86 0