【刷题】 leetcode 面试题 01.06 字符串压缩

简介: 来看效果: 非常好!!!过啦!!!

字符串压缩

来看题目:

依据题目要求,我们必须编写一个函数,确保它能返回一个更为紧凑的字符数组:若压缩后的字符串长度小于原始字符串,则返回压缩后的字符串;反之,则返回原始字符串。本题的挑战核心在于如何有效地判定压缩是否导致了长度缩减,以及如何妥善地将处理后的数据填充进数组之中。接下来,我们将通过两种策略来攻克这一问题。

思路一(双指针顺畅版)

1.初始化检查:

  • 检查输入字符串的长度。
  • 如果字符串长度小于2,则压缩没有意义,直接返回原字符串。

2.设置指针与计数器:

  • 定义两个指针:slowfast,分别初始化在字符串的第一个字符位置。
  • 初始化一个计数器,用于记录重复字符的数量。

3.遍历字符串:

  • 使用fast指针遍历字符串,slow指针指向当前待比较的字符。
  • *fast*slow指向的字符相同时,fast指针向后移动,计数器累加。
  • *fast*slow指向的字符不同,或者fast达到字符串末尾时,进入下一步。

4.记录重复次数:

  • 计算从slowfast-1位置的字符重复次数(因为fast已经指向不同字符或字符串末尾)。
  • 将重复次数转换为字符串格式,以便与字符一同组成压缩后的字符串。

5.构建压缩字符串:

  • slow指向的字符和上一步得到的重复次数字符串拼接起来,形成压缩后的子串。
  • 将这个子串添加到结果字符串中。

6.重置计数器与指针位置:

  • 将计数器归零,准备统计下一组重复字符。
  • slow移动到fast的位置,准备开始下一轮比较。

7.循环直至结束:

  • 重复步骤3到6,直到fast指针遍历完整个字符串。、

8.返回结果:

  • 比较原字符串长度与压缩后的字符串长度。
  • 如果压缩后的字符串长度不小于原字符串长度,返回原字符串。
  • 否则,返回压缩后的字符串作为结果。

这个算法确保了字符串的压缩至少减少了长度如果压缩后没有变短,则保留原字符串。这样的实现既符合了压缩字符串的基本要求,也保证了算法的效率。

char* compressString(char* S){
    int len1 = strlen(S);
    if(len1<=2) return S;
  // 双指针
    char* slow = S;
    char* fast = S;
    //记录次数 每个字母至少出现 1 次
    int count = 1;
  //开辟一个足够大的数组空间
    char* ret = (char*)malloc(sizeof(char) * 100001);
    int i = 0;
    //开始遍历
    while(*fast !='\0'){
      //快指针 后移
        fast = fast + 1;
        //向后移动 直到不同
        while(*fast == *slow){
            fast++;
            count++;
        }

        //计算位数 方便下面的赋值操作
        int n = 0;
        int num = count ;
        while(num){
            num /=10;
            n++;
        }
        int n2 = n;
        // ret 数组赋值
        ret[i++] = *slow;
        while(n--) {
            ret[i + n] = count % 10 + '0' ;
            count /= 10;
        }    
        // 下标后移   
        i += n2;
        // 慢指针移动到快指针位置
        slow = fast;
        //计数重置
        count = 1;
    }

  //结尾 ‘\0’不能忘记
    ret[i] = '\0';

    int len2 = strlen(ret);
    //返回较小的 字符串 
    if(len2 < len1) return ret;
    else return S;
}

思路二(sprintf函数巧解版)

上一步的写入计数的步骤十分繁琐,而使用sprintf函数可以巧妙化解这个问题

因为输入的数据都是 字符 + 数字

将格式化数据写入字符串

该函数将格式化文本组合成一个字符串,其内容与使用printf函数打印时完全一致,但并不直接输出,而是将内容存储在指向str的缓冲区中作为一个C语言风格的字符串。


请注意,缓冲区的大小应足够容纳生成的整个字符串(为了安全性考虑,请参阅snprintf函数获取更安全的版本)。


在内容后面,函数会自动附加一个终止空字符(null terminator)。


在format参数之后,函数期望至少有与format中所需数量相匹配的额外参数。就是可以格式化写入数据


就是可以格式化写入数据

1.遍历字符串并记录相同字符的次数:

  • 使用两个指针,一个指向当前正在比较的字符(slow),另一个指向待比较的字符(fast)。
  • 移动fast指针,直到遇到与slow指向的字符不同的字符,或者到达字符串的末尾。
  • 在移动fast指针的过程中,记录下相同字符出现的次数。

2.写入数据:

  • 使用sprintf函数或者其他字符串格式化方法,将当前字符及其出现的次数转换为一个字符串。
  • 将这个字符串添加到结果字符串中,这样就可以构建出压缩后的字符串。
  • 如果使用sprintf,可以先将次数转换为字符数组,然后将字符和次数连接起来。

3.重复步骤1和2直到遍历结束:

  • 重置计数器,将slow指针移动到fast的位置。
  • 继续执行步骤1和2,直到fast指针遍历完整个字符串。

4.检查压缩后的字符串长度:

  • 在完成压缩后,比较原字符串长度与压缩后的字符串长度。
  • 如果压缩后的字符串长度不小于原字符串长度,返回原字符串。
  • 否则,返回压缩后的字符串作为结果。

在实际编程中,需要考虑一些边界条件和特殊情况,比如字符串为空或者只包含一个字符时的情况。此外,还需要注意sprintf函数的使用,确保不会出现缓冲区溢出等安全问题。

char* compressString(char* S){
  //字符串长度小于 2 直接返回
    int len1 = strlen(S);
    if(len1<=2) return S;
    
    char* ret = (char*)malloc(sizeof(char) * 100001);
    int  count = 1;

    memset( ret, 0x00, sizeof( ret ));
    for ( int i = 0; i < strlen( S ); i++ ) {
        if ( S[i] == S[i+1] ) {
            //前后相等,计数加1 
            count++;
        }
        else {
            //若前后不相等,写入数据, 计数器重置
            sprintf( ret + strlen(ret), "%c%d", S[i], count );
            count = 1;
        }
    }
  //返回较小字符串
    int len2 = strlen(ret);
    if(len2 < len1) return ret;
    else return S;
}

来看效果: 非常好!!!过啦!!!

送给大家一句非常好的句子:

懒惰和贫穷永远是丢脸的,所以每个人都会尽最大努力去对别人隐瞒财产,对自己隐瞒懒惰。

所以加油吧少年!!!

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

相关文章
|
4天前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
4天前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
2月前
|
安全 Java 编译器
【Java基础面试二十九】、说一说你对字符串拼接的理解
这篇文章讨论了Java中字符串拼接的四种常用方式(使用`+`运算符、`StringBuilder`、`StringBuffer`和`String`类的`concat`方法),每种方式适用的场景,以及在不同情况下的性能考量。
|
2月前
|
Java
【Java基础面试二十八】、使用字符串时,new和““推荐使用哪种方式?
这篇文章讨论了在Java中使用字符串时,推荐使用双引号`""`直接量方式而不是使用`new`操作符,因为`new`会在常量池之外额外创建一个对象,导致更多的内存占用。
|
2月前
|
存储 算法
LeetCode第43题字符串相乘
LeetCode第43题"字符串相乘"的解题方法,通过使用数组存储乘积并处理进位,避免了字符串转换数字的复杂性,提高了算法效率。
LeetCode第43题字符串相乘
|
2月前
|
算法 Java
LeetCode第28题找出字符串中第一个匹配项的下标
这篇文章介绍了LeetCode第28题"找出字符串中第一个匹配项的下标"的两种解法:暴力解法和KMP算法,并解释了KMP算法通过构建前缀表来提高字符串搜索的效率。
LeetCode第28题找出字符串中第一个匹配项的下标
|
2月前
|
算法
LeetCode第8题字符串转换整数 (atoi)
该文章介绍了 LeetCode 第 8 题字符串转换整数 (atoi)的解法,需要对字符串进行格式解析与校验,去除前导空格和处理正负号,通过从高位到低位的计算方式将字符串转换为整数,并处理越界情况。同时总结了这几道题都需要对数字的表示有理解。
LeetCode第8题字符串转换整数 (atoi)
|
2月前
|
Python
【Leetcode刷题Python】1467. 两个盒子中球的颜色数相同的概率
本文介绍了LeetCode第50题"Pow(x, n)"的解法,题目要求实现计算x的n次幂的函数,文章提供了递归分治法的详细解析和Python实现代码。
24 0
|
2月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
44 6
|
2月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
82 2
下一篇
无影云桌面