加入气泡的算法
Posted
技术标签:
【中文标题】加入气泡的算法【英文标题】:Algorithm for joining bubbles 【发布时间】:2021-01-03 04:13:53 【问题描述】:有没有更快(或更清洁)的算法来加入气泡,如下所示?
上面的动画示例描述了关闭 8 个气泡之间的 4 个任意间隙。
我想出了这个丑陋的代码,它需要一个arrayK
气泡之间间隙的索引(这个数组保证被排序并且长度为K
),“加入”N
气泡并输出连接气泡的长度。
它有效,但我对它不满意。在给定相同的输入时,是否有更快和/或更简洁的代码输出相同的数据?
void JoinBubbles(const unsigned int* const arrayK, unsigned int K, unsigned int N)
//ArrayK is of size K and is sorted. Obviously K must be less than N and all elements of the array must be less than N-2.
unsigned int h, i, j;
for (i = 0; i < arrayK[0]; i++)
printf("1.");
for (h = 0; h < K; h++)
for (i = h + 1; (i < K) && (arrayK[i - 1] == arrayK[i] - 1); i++);
printf("%d,", i - h + 1);
for (j = arrayK[i - 1] + 2; (i < K) && (j < arrayK[i]); j++)
printf("1.");
h = i - 1;
for (j = arrayK[K - 1] + 2; (j < N + 1); j++)
printf("1,");
printf("\n");
【问题讨论】:
【参考方案1】:对于从0到N-1的所有i
,有两种可能:
i
代表泡沫的结束。在这种情况下,打印气泡的大小,并将大小重置为 1。
i
位于气泡内(因为 i
匹配 K 数组中的下一个条目)。在这种情况下,增加气泡的大小,并将索引更新到 K 数组中。
代码如下:
void JoinBubbles(const unsigned int* const arrayK, unsigned int K, unsigned int N)
int k = 0;
int bubble = 1;
for (int i = 0; i < N; i++)
if (k >= K || i < arrayK[k])
printf("%d.", bubble);
bubble = 1;
else
bubble++;
k++;
printf("\n");
【讨论】:
变量k
(小写)背后的理论是什么?
@GeorgeRobinson k
是arrayK
的索引。所以arrayK[k]
是下一个将被关闭的间隙的位置。条件k >= K
出现在arrayK
的末尾,即所有需要关闭的间隙都已关闭。当i
仍然在下一个间隙的左侧(arrayK[k]
是下一个要关闭的间隙)时,会出现条件i < arrayK[k]
。如果满足任何一个条件,我们就处于泡沫的尽头。如果都不满足条件,我们就到达了一个需要缩小的差距。【参考方案2】:
使用不相交集并集。
见https://www.geeksforgeeks.org/disjoint-set-data-structures/。
假设您在索引 0 处加入气泡,然后合并 0 和 1。
另外,维护一个数组size
。将此初始化为 1,然后对于每次合并,添加要合并的两个集合的大小。
最后,简单的从1扫到N,输出之前没有输出过的气泡的大小(可以用bool数组来实现,记录访问过哪些集合)
随着路径压缩加速,这将在 O(n)
内存和时间复杂度中运行。
实现非常简单,作为读者的练习。 (我的编码风格太丑了)
【讨论】:
以上是关于加入气泡的算法的主要内容,如果未能解决你的问题,请参考以下文章