【问题标题】:comparison function causing problem in vector of vector sorting[leetcode]比较函数导致向量排序的向量问题[leetcode]
【发布时间】:2020-07-22 08:12:16
【问题描述】:

我需要按每个元素向量的第一个元素对向量向量进行排序。它是针对 Leetcode 中的merge intervals 问题。
我为这个问题写了以下代码:

class Solution {
public:
    static bool comparison(const vector<int>& v1, const vector<int>& v2){
        if(v1[0]==v2[0])
            return v1[1]<=v2[1];
        else
            return v1[0]<v2[0];
    }
    
    
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end(), comparison);
        int n = intervals.size();
        
        vector<vector<int>> res;
        if(n >= 1)
            res.push_back(intervals[0]);
        
        for(int i=0;i<n;i++){
            vector<int> rv = res.back();
            vector<int> iv = intervals[i];
            if(rv[1] >= iv[0]){
                res.pop_back();
                res.push_back({min(rv[0], iv[0]), max(iv[1], rv[1])});
            }
            else{
                res.push_back(iv);
            }
        }
        return res;
    }
};

我在比较函数中尝试做的是,如果向量元素的第一个元素相同,我将使用第二个元素进行排序。此代码仅针对一个测试用例给出运行时错误(运行时错误:引用绑定到类型为 'const int' (stl_vector.h) 的空指针)。 如果我将比较函数更改为以下,它适用于所有测试用例:

static bool comparison(const vector<int>& v1, const vector<int>& v2){
        return v1[0]<v2[0];
}

谁能解释一下原因?

【问题讨论】:

  • 传递给比较函数的向量是否多个元素?您确定传递给比较函数的向量实际上根本没有任何元素吗?
  • 如果您阅读the requirements进行比较,您会发现关系必须是strict weak ordering
  • 请注意std::vector::operator&lt; 存在,并且将与comparison 一样对2 个元素向量进行排序
  • @Someprogrammerdude 所有向量都有元素且只有 2 个元素

标签: c++ runtime-error comparator


【解决方案1】:

比较器需要满足命名要求Compare,这需要严格的弱排序。您必须满足的一个条件是:

对于所有人,comp(a,a) == false

例如

comparison({0, 0}, {0, 0});

产生true。由于您的比较器不满足所有要求,您会得到未定义的行为,这在您的情况下表现为崩溃。

要恢复严格的弱排序,请将&lt;= 替换为&lt;

static bool comparison(const vector<int>& v1, const vector<int>& v2){
    if(v1[0]==v2[0])
        return v1[1] < v2[1];
    else
        return v1[0] < v2[0];
}

您还应该首先检查向量的长度,否则您将面临越界访问的风险。

【讨论】:

  • 谢谢 churill。只是好奇,如果需要一个在比较 {a,a} 时返回 true 的比较器,我该怎么办?
  • 当然,您可以将这样的比较器用于您自己的算法或仅比较两个元素时。但不适用于std::sort,该算法依赖于某些条件才能正常工作。最后,这是由于排序应该如何工作并且不能更改的数学定义。
【解决方案2】:

我认为我们不需要在 std::sort 中进行比较,因为它已经根据间隔的开始进行了排序。如果您删除了您的算法就可以正常工作:

struct Solution {
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end());
        int n = intervals.size();

        vector<vector<int>> res;

        if (n >= 1) {
            res.push_back(intervals[0]);
        }

        for (int i = 0; i < n; i++) {
            vector<int> rv = res.back();
            vector<int> iv = intervals[i];

            if (rv[1] >= iv[0]) {
                res.pop_back();
                res.push_back({min(rv[0], iv[0]), max(iv[1], rv[1])});

            } else {
                res.push_back(iv);
            }
        }

        return res;
    }
};

更传统一点:

#include <vector>
#include <algorithm>
#include <cstdint>

struct Solution {
    static std::vector<std::vector<int>> merge( std::vector<std::vector<int>> &intervals) {
        if (intervals.size() < 2) {
            return intervals;
        }

        std::sort(std::begin(intervals), std::end(intervals));

        std::vector<std::vector<int>> merged_intervals;
        merged_intervals.push_back(intervals[0]);

        for (std::size_t index = 1; index < intervals.size(); index++) {
            if (merged_intervals.back()[1] >= intervals[index][0]) {
                merged_intervals.back()[1] = std::max(merged_intervals.back()[1], intervals[index][1]);

            } else {
                merged_intervals.push_back(intervals[index]);
            }
        }

        return merged_intervals;
    }
};

参考文献

  • 有关其他详细信息,您可以查看Discussion Board。有很多公认的解决方案,有各种languages 和解释、高效的算法,以及渐近的time/space 复杂性分析1, 2

【讨论】:

    【解决方案3】:

    std::vector::operator[] 不执行边界检查。由于您不检查向量的大小,因此当您放入空向量时,comparison() 会导致未定义的行为。

    通过更改 comparison() 的行为,您还可能会更改排序的行为,这可能导致传入空向量或不传入空向量。尽管如此,您的运算符还是坏了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-04
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-16
      • 2018-04-19
      相关资源
      最近更新 更多