【问题标题】:Algorithm to merge a small sorted list into a larger sorted list, without duplicates, in linear time在线性时间内将一个小的排序列表合并到一个更大的排序列表中的算法,没有重复
【发布时间】:2020-01-30 06:54:16
【问题描述】:

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

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

这是一个接收列表并使用新列表“temp”合并它们的函数。注意:这使用了自定义列表,但您可以假设插入方法在 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]

有什么建议吗?

【问题讨论】:

  • 假设您想将一个新元素插入到一个排序列表中,这样结果将是一个线性排序的列表(例如,新元素在正确的位置)时间并创建一个临时列表。你知道怎么做吗?
  • @Beta 这如何转化为这个问题?
  • 因为如果您可以找到插入点并插入(或者如果节点已经存在则不插入)一个节点,您需要做的就是一次又一次地做,直到列表合并。请记住在您刚刚插入(或未插入)的节点之后开始寻找新的插入点。

标签: c++ list merge


【解决方案1】:

鉴于插入操作是 O(1),您可以在线性时间内进行就地合并,这通常适用于所有列表实现。

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

让我们使用以下符号:smaller list 是我们不改变的列表。 较大的列表是我们通过插入较小列表中的元素来改变的列表。

  • 从两个指向每个列表开头的迭代器开始
  • 如果两个迭代器的值相同,则递增较小列表的迭代器(跳过重复项)
  • 如果较大列表的迭代器处的值较大(或者我们到达了较大列表的末尾),则将较小列表中的值插入到它之前,增加较小列表的迭代器
  • 否则,增加较大列表的迭代器。
  • 如果较小列表的迭代器到达末尾,则终止循环。

代码如下:

#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;
        }
    }
}

【讨论】:

  • 我已经尝试过这段代码,但我仍然只将一个列表作为参数传递并使用“this->”来引用另一个列表。 AKA 我这样调用函数:list2.mergeNoDups(list1)。我收到“进程返回 -1073741819 (0xC0000005)”错误。使用更大 = 0 1 2 5 6 和更小 = 0 1 的示例,看起来“其”超出了较小列表的末尾。
  • 这里是在线 c++ 编译器的 URL cpp.sh/42ufb 您的示例似乎可以正确运行。也许问题出在自定义 List 实现上?
  • Insert 应该在迭代器指定的元素之前插入一个元素。是这样实现的吗?
  • 可以分享一下修改后的mergeNoDups函数的List实现吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 2013-11-10
  • 2014-03-30
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多