RLE序列,设置值
假设我有一个任意的 RLE 序列。 (对于那些不知道的人来说,RLE 将像 [4 4 4 4 4 6 6 1 1] 这样的数组压缩为 [(5,4) (2,6) (2,1)]。首先是 a 的数量运行中的特定整数,然后是数字本身。)
如何确定一种算法来在给定索引处设置值而不解压缩整个内容?例如,如果您设置(0,1),RLE 将变为 [(1,1) (4,4) (2,6) (2,1)]。 (在集合中,第一个值是索引,第二个值是值)
此外,我已将此压缩序列划分为条目的 ArrayList。也就是说,每个条目都是以下之一: (1,1),其中它具有金额和值。
我正在尝试找到一种有效的方法来做到这一点,现在我只能想到有太多 if 语句被认为是干净的方法。有很多可能的变化:例如,如果给定值分割现有条目,或者它与现有条目具有相同的值,等等......
任何帮助将不胜感激。我现在正在研究一种算法,以下是其中的一些:
while(i<rleAL.size() && count != index)
{
indexToStop=0;
while(count<index || indexToStop == rleAL.get(i).getAmount())
{
count++;
indexToStop++;
}
if(count != index)
{
i++;
}
}
正如您所看到的,这变得越来越草率......
谢谢!
Say I have an arbitrary RLE Sequence. (For those who don't know, RLE compresses an array like [4 4 4 4 4 6 6 1 1] into [(5,4) (2,6) (2,1)]. First comes the number of a particular integer in a run, then the number itself.)
How can I determine an algorithm to set a value at a given index without decompressing the whole thing? For example, if you do set(0,1) the RLE would become [(1,1) (4,4) (2,6) (2,1)]. (In set, the first value is the index, the second is the value)
Also, I've divided this compressed sequence into an ArrayList of Entries. That is, each Entry is one of these: (1,1) where it has an amount and value.
I'm trying to find an efficient way to do this, right now I can just think of methods that have WAY too many if statements to be considered clean. There are so many possible variations: for example, if the given value splits an existing entry, or if it has the same value as an existing entry, etc...
Any help would be much appreciated. I'm working on an algorithm now, here is some of it:
while(i<rleAL.size() && count != index)
{
indexToStop=0;
while(count<index || indexToStop == rleAL.get(i).getAmount())
{
count++;
indexToStop++;
}
if(count != index)
{
i++;
}
}
As you can see this is getting increasingly sloppy...
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
RLE 通常不擅长更新,正是出于上述原因。将 ArrayList 更改为 LinkedList 不会有太大帮助,因为 LinkedList 在除插入之外的所有操作中都非常慢(即使使用插入,您也必须已经使用例如 ListIterator 持有对特定位置的引用)。
不过,谈到最初的问题,没有必要全部解压。您所需要做的就是找到正确的位置(汇总计数),这是线性时间的(考虑跳过列表以使其更快),之后您将只有四个选项:
显然,操作是相同的:
(请注意,如果您有跳过列表,则也必须更新它们。 )
更新:如果要更新的块的长度为 1(正确),则会变得更有趣。尽管如此,这一切仍然是微不足道的:无论如何,更改仅限于最多三个块。
RLE is generally bad at updates, exactly for the reason stated. Changing ArrayList to LinkedList won't help much, as LinkedList is awfully slow in everything but inserts (and even with inserts you must already hold a reference to a specific location using e.g. ListIterator).
Talking about the original question, though, there's no need to decompress all. All you need is find the right place (summing up the counts), which is linear-time (consider skip list to make it faster) after which you'll have just four options:
The actions are the same, obviously:
(Note though if you have skip lists, you must update those as well.)
Update: it gets more interesting if the block to update is of length 1, true. Still, it all stays as trivial: in any case, the changes are limited to maximum of three blocks.