当前位置: 首页 > 知识库问答 >
问题:

合并排序删除重复项

甘永春
2023-03-14

我试图通过合并排序对数组进行排序,并在排序时删除我认为相等的元素。我递归调用合并排序,然后合并。

到了这一点,我发现a和c是重复的。

a b | c d

我根据特定的标准决定我想要哪一个,我选择c。我递增右手计数器和左手计数器,比较b和d。假设我选择d,然后我选择b。我希望我的最终列表只有元素

c d b  

但是,发生的事情是在下一个递归调用中,startend是0和3,因此d在下一次调用时在数组中列出两次。合并过程使用的数组是:

c d b d

这是代码。提前谢谢。

private static void merge(int[] data, int start, int mid, int end)
{
    int firstCopied=0;
    int secondCopied=0;
    int index=0;
    int length=end-start+1;

    int[] temp = new int[end-start+1];
    int firstSize=mid-start+1;
    int secondSize=end-mid;

    while(firstCopied < firstSize && secondCopied < secondSize)
    {
        if(data[start+firstCopied] < data[mid+1+secondCopied])
        {
            temp[index++] = data[start+firstCopied];
            firstCopied++;
        }

        else if(data[start+firstCopied] > data[mid+1+secondCopied])
        {
            temp[index++] = data[mid+1+secondCopied];
            secondCopied++;
        }

        else if(data[start+firstCopied]==data[mid+1+secondCopied])
        {
            boolean result = PickOne();

            if(result)
            {
                temp[index++] = data[start+firstCopied];
            }
            else
            {
                temp[index++] = data[mid+1+secondCopied];
            }

            firstCopied++;
            secondCopied++;
            length--;
        }
    }
    while(firstCopied < firstSize)
    {
        temp[index++] = data[start+firstCopied];
        firstCopied++;
    }

    while(secondCopied < secondSize)
    {
        temp[index++] = data[mid+1+secondCopied];
        secondCopied++;
    }

    for(int i=0; i<length; i++)
    {
        data[start+i]=temp[i];
    }

}

共有3个答案

尹俊贤
2023-03-14

首先确保[start,mid]和[mid 1,end]中的元素已排序且唯一。否则,代码运行后将存在重复项。

呼延哲
2023-03-14

您的合并从概念上改变了数组的长度。但是没有代码可以真正截断数据。我建议您返回长度(而不是void),并使用一些最终的后处理步骤将数据截断为最终长度,或者至少避免打印那些超过结束元素的数据。

柯默
2023-03-14

C标准库的理念是使用能做好一件事的算法。最好遵循这种方法,因为它会导致更多可重用的代码。

例如,这里有一个mergesort草图,后面是对std::唯一的调用

template<typename BiDirIt>
void merge_sort(BiDirIt first, BiDirIt last)
{
    auto const N = std::distance(first, last);
    if (N < 2) return;

    // sort each part individually, then merge back in-place
    auto middle = first + N / 2;
    merge_sort(first, middle);
    merge_sort(middle, last);
    std::inplace_merge(first, middle, last);
}    

int data[] = { /* your data */ };
merge_sort(std::begin(data), std::end(data));

auto it = std::unique(std::begin(data), std::end(data));
for (auto ut = std::begin(data); ut != it; ++ut) {
    // process unique data
}

如果数据位于std::vector而不是C数组中,则可以调用v.erase(v.begin(),it) 以实际擦除非唯一数据。

 类似资料:
  • 问题内容: 我有两个列表需要合并,第二个列表忽略了第一个列表的重复项。..有点难以解释,所以让我展示一个代码看起来像什么,以及我想要什么的示例。 您会注意到结果具有第一个列表, 包括 其两个“ 2”值,但是second_list也具有附加的2和5值这一事实并未添加到第一个列表中。 通常,对于这样的事情,我会使用集合,但是first_list上的集合会清除它已经具有的重复值。所以我只是想知道什么是实

  • 问题内容: 我有一个未排序的整数数组,其值的范围从Integer.MIN_VALUE到Integer.MAX_VALUE。数组中可以有任意整数的多个重复项。我需要返回一个删除了所有重复项的数组,并且还需要保持元素的顺序。 例: 输出应为{7,8,1,9,0,2} 我知道可以使用解决此问题,但我需要一个不占用大量缓冲区空间的解决方案。 问题答案: 您可以使用Java 8 Arrays 方法从数组中获

  • 结果:[1,2,3,3,3,4,4][1,2,3,3,3,4,4]

  • 我有一个名为$PRODUCTS_LIST的数组,它填充了数据,结构如下: 如果数组中的值具有相同的描述和条件,我正在尝试从数组中删除任何重复值,并合并重复值中的数量。 我尝试将数据设置为临时数组,以便能够将两个数组比较为foreach语句。类似这样的事情:

  • 请注意,在转向您之前,我已经浏览了各种帖子。事实上,我尝试实现中提供的解决方案:基于“notin”条件从数据帧中删除行 我的问题如下。让我们假设我有一个巨大的数据帧,我想删除重复的数据帧。我很清楚我可以使用drop_duplicates,因为这是最快的最简单的方法。然而,我们的老师希望我们创建一个包含重复项ID的列表,然后根据这些值是否包含在上述列表中删除它们。 现在,让我们看看输出: 因此,我得

  • 我有一个问题: 对象显示给定一个排序数组,删除重复的元素,使每个元素只出现一次,并返回新的长度。不要为另一个数组分配额外的空间,必须在内存不变的情况下这样做。例如,给定输入数组Nums=[1,1,2],你的函数应该返回长度=2,Nums的前两个元素分别为1和2。你在新的长度之外留下什么并不重要。 我使用HashSet来回答这个问题,但结果总是显示[1,1]。我想不出来有人能帮我知道问题出在哪里吗?