Python面试宝典第49题:字符串压缩

题目

给你一个字符数组chars ,请使用下述算法进行压缩。

1、从一个空字符串s开始,对于chars中的每组连续重复字符 :

(1)如果这一组长度为1 ,则将字符追加到s中。

(2)否则,需要向s追加字符,后跟这一组的长度。

2、压缩后得到的字符串s不应该直接返回 ,需要转储到字符数组chars中。需要注意的是,如果组长度为10或10以上,则在chars数组中会被拆分为多个字符。

请在修改完输入数组后 ,返回该数组的新长度。

备注:chars[i]可以是小写英文字母、大写英文字母、数字或符号。

示例 1:

python 复制代码
输入:chars = ["a","a","b","b","c","c","c"]
输出:返回6 ,输入数组的前6个字符应该是["a","2","b","2","c","3"]。
解释:"aa"被"a2"替代,"bb"被"b2"替代,"ccc"被"c3"替代。

示例 2:

python 复制代码
输入:chars = ["a"]
输出:返回1,输入数组的前1个字符应该是["a"]。
解释:唯一的组是"a",它保持未压缩,因为它是一个字符。

示例 3:

python 复制代码
输入:chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"]
输出:返回4,输入数组的前4个字符应该是["a","b","1","2"]。
解释:由于字符"a"不重复,所以不会被压缩,"bbbbbbbbbbbb"被"b12"替代。

使用栈

使用栈来求解本题的基本思想是:利用栈这种数据结构来存储连续重复字符的信息。解题的主要步骤如下。

1、初始化栈。创建一个栈,用于存放字符及其重复次数。

2、遍历数组。从左至右,遍历输入数组chars。

3、处理字符。如果栈为空,或当前字符与栈顶字符不同,将当前字符及其初始计数1压入栈中。如果当前字符与栈顶字符相同,增加栈顶计数。

4、构建压缩后的字符串。当遍历完整个数组后,从栈中弹出字符及其计数,并将它们按照规则添加到结果数组中。

根据上面的算法步骤,我们可以得出下面的示例代码。

python 复制代码
def string_compression_by_stack(chars):
    stack = []
    write_index = 0

    for read_index in range(len(chars)):
        # 如果栈为空,或者当前字符与栈顶字符不同
        if not stack or chars[read_index] != stack[-1][0]:
            # 入栈
            stack.append([chars[read_index], 1])
        else:
            # 更新计数
            stack[-1][1] += 1

    # 构建压缩后的字符串
    for char, count in stack:
        # 写入字符
        chars[write_index] = char
        write_index += 1
        # 如果计数大于1,则写入计数
        if count > 1:
            # 将计数按位写入
            for digit in str(count):
                chars[write_index] = digit
                write_index += 1

    return write_index

chars = ["a", "a", "b", "b", "c", "c", "c"]
new_length = string_compression_by_stack(chars)
print(new_length)
print(chars[:new_length])

chars = ["a"]
new_length = string_compression_by_stack(chars)
print(new_length)
print(chars[:new_length])

chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"]
new_length = string_compression_by_stack(chars)
print(new_length)
print(chars[:new_length])

双指针法

双指针法利用了一个基本事实:压缩后的字符数组通常情况下比原数组要短,最坏情况下一样长。我们可以使用两个指针:read_index和write_index。read_index用于读取原数组中的字符,write_index用于写入压缩后的结果。遍历原数组,当遇到相同的字符时,更新计数。当遇到不同的字符时,将当前字符及其计数(如果大于1)写入到chars数组中,并更新write_index。使用双指针法求解本题的主要步骤如下。

1、初始化,将read_index和write_index置为0。

2、遍历chars数组,使用read_index逐个读取字符,并进行以下操作。

(1)使用一个变量count,记录当前字符的重复次数。

(2)当遇到不同的字符时,将当前字符和其重复次数写入chars数组的write_index位置,并更新 write_index。

3、返回write_index作为新长度。

根据上面的算法步骤,我们可以得出下面的示例代码。

python 复制代码
def string_compression_by_two_pointers(chars):
    read_index = 0
    write_index = 0
    n = len(chars)

    while read_index < n:
        char = chars[read_index]
        count = 0
        # 一直遍历到不同的字符为止
        while read_index < n and chars[read_index] == char:
            read_index += 1
            count += 1
        
        # 先写入字符
        chars[write_index] = char
        write_index += 1
        
        # 如果计数大于1,再写入计数
        if count > 1:
            for digit in str(count):
                chars[write_index] = digit
                write_index += 1

    return write_index

chars = ["a", "a", "b", "b", "c", "c", "c"]
new_length = string_compression_by_two_pointers(chars)
print(new_length)
print(chars[:new_length])

chars = ["a"]
new_length = string_compression_by_two_pointers(chars)
print(new_length)
print(chars[:new_length])

chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"]
new_length = string_compression_by_two_pointers(chars)
print(new_length)
print(chars[:new_length])

总结

使用栈来求解本题时,需要遍历输入数组一次,每个字符至多入栈和出栈各一次。故时间复杂度为O(n),其中n是输入数组的长度。其空间复杂度为O(n),需要额外的空间来存储栈。

双指针法的时间复杂度也为O(n),但其空间复杂度仅为O(1),不需要额外的空间。与使用栈的方法相比,双指针法效率更高,但在理解上可能稍微复杂一些。

相关推荐
K2I-30 分钟前
UCI中Steel Plates Faults不平衡数据集处理
python
蓑笠翁00130 分钟前
Django REST Framework 全面指南:从模型到完整API接口开发
后端·python·django
Miraitowa_cheems35 分钟前
LeetCode算法日记 - Day 64: 岛屿的最大面积、被围绕的区域
java·算法·leetcode·决策树·职场和发展·深度优先·推荐算法
Christo31 小时前
关于K-means和FCM的凸性问题讨论
人工智能·算法·机器学习·数据挖掘·kmeans
感谢地心引力1 小时前
【Python】基于 PyQt6 和 Conda 的 PyInstaller 打包工具
数据库·python·conda·pyqt·pyinstaller
_不会dp不改名_1 小时前
leetcode_1382 将二叉搜索树变平衡树
算法·leetcode·职场和发展
greentea_20132 小时前
Codeforces Round 173 B. Digits(2043)
c++·算法
渣哥2 小时前
不加 @Primary?Spring 自动装配时可能直接报错!
javascript·后端·面试
xiaohanbao093 小时前
Transformer架构与NLP词表示演进
python·深度学习·神经网络
m0_743106463 小时前
LOBE-GS:分块&致密化效率提升
人工智能·算法·计算机视觉·3d·几何学