【问题标题】:Wrong Count in Merge Sort: Counting Inversions合并排序中的错误计数:计数反转
【发布时间】:2018-09-18 13:15:46
【问题描述】:

Hackerrank problem 要求自定义实现合并排序以跟踪反转(我认为交换是一种更好的引用方式。),但我无法捕获某些正确的计数数据集。

在我当前的实现中被一个失败的测试用例阻塞,向量 std::vector<int> data { 7, 5, 3, 1 }; 产生:

Unsorted
- - - - - - - - - -
7 5 3 1

| Left  > 7 5
| Right > 3 1
    | Left  > 7
    | Right > 5
    | Left  > 3
    | Right > 1


4 Inversions
Sorted
- - - - - - - - - -
1 3 5 7

预期输出是 6 次反转,但我的算法计数 4 并且不太确定为什么我的代码在该数据集上失败,但适用于其他测试用例黑客等级。

我的计划

#include <cstddef>
#include <iostream>
#include <vector>

void merge(std::vector<int> &data, std::vector<int> left, std::vector<int> right, long &inversions)
{
    int leftSize = left.size();
    int rightSize = right.size();

    int leftIndex = 0;
    int rightIndex = 0;

    std::vector<int> temp;
    while (leftIndex < leftSize && rightIndex < rightSize)
    {
        if (left[leftIndex] <= right[rightIndex]) {
            temp.push_back(left[leftIndex++]);
        }
        else {
            temp.push_back(right[rightIndex++]);
            inversions++;
        }
    }

    while (leftIndex < leftSize) {
        temp.push_back(left[leftIndex++]);
    }
    while (rightIndex < rightSize) {
        temp.push_back(right[rightIndex++]);
    }

    for(size_t i = 0; i < temp.size(); i++)
    {
        data[i] = temp[i];
    }
}

void mergeSort(std::vector<int> &data, unsigned firstElementIndex, unsigned lastElementIndex, long &inversions, std::string s)
{
    if (data.size() <= 1) {
        return;
    }

    std::vector<int> left;
    std::vector<int> right;
    unsigned pivot = data.size() / 2;

    printf("%s| Left  > ", s.c_str());
    for (unsigned i = firstElementIndex; i < pivot; ++i) {
        left.push_back(data[i]);
    } for (auto element : left) {
        std::cout << element << ' ';
    }
    printf("\n");


    printf("%s| Right > ", s.c_str());
    for (unsigned i = pivot; i <= lastElementIndex; ++i) {
        right.push_back(data[i]);
    } for (auto element : right) {
        std::cout << element << ' ';
    }
    printf("\n");

    s.append("    ");
    mergeSort(left, firstElementIndex, pivot - 1, inversions, s);
    mergeSort(right, pivot - pivot, data.size() - 1 - pivot, inversions, s);
    merge(data, left, right, inversions);
}

long countInversions(std::vector<int> &data)
{
    long inversions = 0.0;
    std::string s = "";
    mergeSort(data, 0, data.size() - 1, inversions, s);

    return inversions;
}



   /* 
   If I wanted to hack this I could
   long countInversions(std::vector<int> &data)
   {
    long inversions = 0.0;
    std::string s = "";

    std::vector<int> haxor { 7, 5, 3, 1 };

    if (data == haxor)
    {
        inversions = 6;
    }
    else
    {
        mergeSort(data, 0, data.size() - 1, inversions, s);
    }

    return inversions;
   }
   */

int main()
{
    std::vector<int> data { 7, 5, 3, 1 };

    for (auto i = 0; i < 10; i++) {
        // data.push_back( rand() % 100 + 1 );
    }

    printf("Unsorted\n- - - - - - - - - -\n");
    for (auto element : data) {
        std::cout << element << ' ';
    }
    printf("\n\n");

    long result = countInversions(data);
    printf("\n\n%ld Inversions\n", result);

    printf("Sorted\n- - - - - - - - - -\n");
    for (auto element : data) {
        std::cout << element << ' ';
    }
    printf("\n");

    return 0;
}

【问题讨论】:

    标签: c++ vector mergesort


    【解决方案1】:

    你应该阅读关于 Hackerrank 的讨论:https://www.hackerrank.com/challenges/ctci-merge-sort/forum

    问题描述不佳-论坛中的第三次讨论说明了该怎么做。

    编辑: 以下是关于我提到的讨论的更多信息:

    andras_igneczi 2 年前 我真的不明白这个例子。为什么我们必须在这个数组的情况下进行 4 次交换:2 1 3 1 2?如果我们交换

    【讨论】:

    • 感谢您引用此评论“确保使用 long 来跟踪交换!如果使用 int,由于最后三分之一的整数溢出或这样的情况。”?
    • 添加了一些讨论中的信息。
    • 很好的发现,我可能只是为那个用例硬编码以获得通过。这个问题很傻。用 hack 更新了我的帖子。我只通过了 16 个测试用例中的 4 个,所以我认为我的代码存在一些更深层次的问题。
    • HackerRank 上的很多问题并不理想。我对几乎所有的 C++ 课程都感到非常失望——他们真的错过了如何使用大部分功能的重点。好消息是,如果您对它们进行足够的探索,大多数讨论中都有解决方法。
    猜你喜欢
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多