在线性时间内将小的排序列表合并为更大的排序列表的算法,没有重复项

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在线性时间内将小的排序列表合并为更大的排序列表的算法,没有重复项相关的知识,希望对你有一定的参考价值。

我有两个元素数量不同的列表,每个列表至少包含一个重复项。我希望在最坏的线性时间内将较小的列表合并为较大的列表。

我可以通过使用第三个临时列表来解决这个问题,但是我特别需要将较小的列表合并到较大的列表中,而不是创建第三个列表。

这里是一个接收列表并使用新列表“ temp”合并它们的函数。注意:这使用了自定义列表,但是您可以假定insert方法在STL版本上是相同的。

void mergeNoDups(const List<Object> & rhs)
    
        List<int> temp;

        for (const_iterator iter = this->begin(), iter2 = rhs.begin(); iter != this->end() || iter2 != rhs.end();)
        
            if((iter != end()) && iter2 == end() || (*iter < *iter2))
            
                temp.push_back(*iter);
                ++iter;
            
            else if (*iter == *iter2)
            
                ++iter2;
            
            else if (*iter > *iter2)
            
                temp.push_back(*iter2);
                ++iter2;
            
        
    

给出输入:

list1 = [0 1 2 5 6]

list2 = [3 4 5 7]

list1应该是:

列表1 = [0 1 2 3 4 5 6 7]

任何提示?

答案

您可以在线性时间内进行就地合并,因为插入操作为O(1),对于所有列表实现通常都是如此。

您的解决方案没有太大区别。该算法非常相似:

让我们使用以下符号:较小列表是我们不变异的列表。 较大列表是我们通过插入较小列表中的元素进行突变的列表。

  • 以两个指向每个列表开头的迭代器开头
  • 如果两个迭代器的值相同,则递增较小列表的迭代器(跳过重复项)
  • 如果较大列表的迭代器上的值较大(或我们到达较大列表的末尾),则在较小列表的前面插入该值,然后递增较小列表的迭代器
  • 否则,增加较大列表的迭代器。
  • 如果较小列表的迭代器到达末尾,则终止循环。

代码如下:

#include <list>

template<typename T>
void mergeNoDups(std::list<T>& larger, const std::list<T>& smaller)

    typename std::list<T>::iterator itl = larger.begin();
    typename std::list<T>::const_iterator its = smaller.begin();

    while (its != smaller.end())
    
        if (itl == larger.end() || *itl > *its)
        
            larger.insert(itl, *its);
            ++its;
        
        else if (*itl == *its)
        
            ++its;
        
        else // *itl < *its
        
            ++itl;
        
    

以上是关于在线性时间内将小的排序列表合并为更大的排序列表的算法,没有重复项的主要内容,如果未能解决你的问题,请参考以下文章

归并排序

LeetCode刷题之合并排序链表

在 Delphi 中是不是可以将枚举合并为更大的枚举?

算法初识:常用的五种排序算法-冒泡排序

八大排序之归并排序

数据结构与算法之三 深入学习排序