如何解决为什么自定义比较器时出现有关空指针的错误 根据Pete的建议进行编辑:
我正在尝试通过Leetcode解决此问题:https://leetcode.com/problems/merge-intervals
给出间隔的集合,合并所有重叠的间隔。
示例1:
Input: intervals = [[1,3],[2,6],[8,10],[15,18]] Output: [[1,18]] Explanation: Since intervals [1,3] and [2,6] overlaps,merge them into [1,6].
示例2:
Input: intervals = [[1,4],[4,5]] Output: [[1,5]] Explanation: Intervals [1,4] and [4,5] are considered overlapping.
注意:输入类型已于2019年4月15日更改。请重置为默认代码定义以获取新的方法签名。
约束:
intervals[i][0] <= intervals[i][1]
我只是有一个简单的主意:对输入进行排序并进行合并。
这是我的代码:
vector<vector<int>> merge(vector<vector<int>> &intervals)
{
vector<vector<int>> res;
if (intervals.empty()) {
return res;
}
std::sort(intervals.begin(),intervals.end(),[](const vector<int> e1,const vector<int> e2) {
if (e1[0] == e2[0]) {
return e1[1] <= e2[1]; // ERROR!!!
}
return e1[0] < e2[0];
});
res.push_back(intervals[0]);
for (size_t i = 1; i < intervals.size(); i++) {
if (res.back()[1] >= intervals[i][0]) {
if (res.back()[1] <= intervals[i][1]) {
res.back()[1] = intervals[i][1];
}
} else {
res.push_back(intervals[i]);
}
}
return res;
}
实际上,错误来自std::sort
行。
Line 1052: Char 9: runtime error: reference binding to null pointer of type 'const __gnu_cxx::__alloc_traits<std::allocator<int>,int>::value_type' (aka 'const int') (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1061:9
但是如果我按如下方式更改比较器:
std::sort(intervals.begin(),const vector<int> e2) {
if (e1[0] == e2[0]) {
return e1[1] < e2[1]; // change <= into <
}
return e1[0] < e2[0];
});
它将按预期运行,没有任何错误。
我不知道为什么。
解决方法
在您的比较器中,此比较:
return e1[1] <= e2[1];
对要比较的元素不满足严格弱排序的要求。例如如果
e1: {1,2}
e2: {1,2}
然后比较e1
和e2
将返回true
,而不考虑比较顺序。
违反std::sort
的此要求将导致未定义的行为。在这种情况下,UB消毒剂会为您帮助诊断问题。
另一方面,这种比较:
return e1[1] < e2[1];
非常好,因为它会根据需要建立严格弱排序。
,-
看起来不错!快到了!
-
我们将执行常规的
std::sort()
然后使用std::min()
和std::max()
,而不必使用比较器:
// Most of headers are already included;
// Can be removed;
#include <iostream>
#include <cstdint>
#include <vector>
// The following block might slightly improve the execution time;
// Can be removed;
static const auto improve_runtime = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
struct Solution {
static const std::vector<std::vector<int>> merge(
std::vector<std::vector<int>>& intervals
) {
std::sort(std::begin(intervals),std::end(intervals));
std::vector<std::vector<int>> merged;
if (std::size(intervals) >= 1) {
merged.emplace_back(intervals[0]);
}
for (std::size_t index = 0; index < std::size(intervals); ++index) {
const std::vector<int> interval = intervals[index];
const std::vector<int> tail = merged.back();
if (tail[1] >= interval[0]) {
merged.pop_back();
merged.emplace_back(std::vector<int> {
std::min(tail[0],interval[0]),std::max(interval[1],tail[1])
});
} else {
merged.emplace_back(interval);
}
}
return merged;
}
};
// int main() {
// std::vector<std::vector<int>> intervals = {{1,3},{2,6},{8,10},{15,18}};
// std::vector<std::vector<int>> merged = Solution().merge(intervals);
// for (auto& interval : merged) {
// std::cout << "[" << interval[0] << "\t" << interval[1] << "]\n";
// }
// }
PS:
- LeetCode在C ++ 17上运行。
- 除了比赛外,还要确保始终使用
std::
。
- 这是您的有效算法,无需使用比较器:
// Most of headers are already included;
// Can be removed;
#include <iostream>
#include <cstdint>
#include <vector>
// The following block might slightly improve the execution time;
// Can be removed;
static const auto improve_runtime = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
struct Solution {
std::vector<std::vector<int>> merge(
std::vector<std::vector<int>>& intervals
) {
std::vector<std::vector<int>> res;
if (intervals.empty()) {
return res;
}
std::sort(intervals.begin(),intervals.end());
res.push_back(intervals[0]);
for (std::size_t i = 1; i < intervals.size(); i++) {
if (res.back()[1] >= intervals[i][0]) {
if (res.back()[1] <= intervals[i][1]) {
res.back()[1] = intervals[i][1];
}
} else {
res.push_back(intervals[i]);
}
}
return res;
}
};
int main() {
std::vector<std::vector<int>> intervals = {{1,18}};
std::vector<std::vector<int>> merged = Solution().merge(intervals);
for (auto& interval : merged) {
std::cout << "[" << interval[0] << "\t" << interval[1] << "]\n";
}
}
根据Pete的建议进行编辑:
包含两个连续下划线( optimize )和 以下划线和大写字母开头的名称是 保留供实现使用。不要在您的代码中使用它们。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。