技术提高是一个循序渐进的过程,所以我讲的leetcode算法题从最简单的level开始写的,然后到中级难度,最后到hard难度全部完。目前我选择C语言,Python和Java作为实现语言,因为这三种语言还是比较典型的。由于篇幅和精力有限,其他语言的实现有兴趣的朋友请自己尝试。
如果有任何问题可以在文章后评论或者私信给我。
如果有朋友希望我讲些其他话题,请在评论区留言或者私信给我。
持续分享,敬请关注。
LeetCode 1313. 解压缩行程编码列表(Decompress Run-Length Encoded List)
问题描述:
给定一个nums整数列表,这些整数表示使用行程编码(Run-Length Encoded)压缩的列表。
行程编码列表:
每对相邻的元素[freq, val] = [nums[2i], nums[2i+1]] (i >= 0)。对于每个这样的对,freq 表示 原数据中,连续的出现数值val的数量。
返回解压缩后的列表。
注:
· 2 <= nums.length <= 100;
· nums.length % 2 == 0;
· 1 <= nums[i] <= 100;
示例:
C语言实现:
RLE是一种非常简单的"压缩"编码技术,在文本和二进制数据的无损压缩中可能会碰到。 据说windows的图形压缩就用到了这个技术。
RLE对连续重复的数据具有很好的压缩作用,如果数据非常离散,压缩效果就会比较差,RLE对于连续数据小于2的情况起不到压缩作用,甚至会导致压缩结果比原来的大的情况,所以压缩二字要打个引号。
对于RLE解压来说,最终的结果的长度是依赖nums中所有偶数下标数的和。实现过程有3种办法:
- 先初始化res,长度设置为一个初始值,遍历nums填充的时候,如果预期长度大于当前res长度的时候,增加res的长度,在填充;
- 遍历nums,计算出目标结果res的长度,从而创建res,然后再遍历一次nums来填充res;
- 创建一个可以动态扩容的容器,这样考虑长度的问题,直接填充,然后转换成结果类型;
对于C 语言实现我们使用的是第一种方法。
Java的实现我们尝试用第二种方法。
首先创建动态创建数组res,长度初始化为256,后面看情况再动态调整。
所以,这个长度任意,但不要太小,太小,需要频繁的调整,太大浪费资源。此外,实际生产中,建议值为16的幂,这样可以起到一定的对齐作用。
然后遍历nums。
在遍历过程中,首先要检查res的长度是否会超过预期,这要根据res当前已用的长度和预期要填充的长度来判断。如果超长了,那么调用realloc调整res的大小,注意realloc这个调用,它可能会为res分配一个新的地址,realloc成功的话会返回对象的起始地址,所以一定要将这个地址重新赋值给res。
然后开始一个内部循环,不断减小频率值以填充新数据到res中。
代码如下:
java语言实现:
Java的实现用第一种实现相对复杂,因为要频繁的创建 int[] 对象,所以效率也不见得好。
用第三种办法,实现很简单,可以创建一个List容器来实现,但是对于java来说List转换成int[]是一个硬伤。
所以最好的实现是第二种。
代码如下:
python语言实现:
Python 用的是第三种实现。
代码如下: