1、问题分析
题目链接:https://leetcode-cn.com/problems/find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/
本质上就是一个求全源最短路径问题,但是需要注意的是leetCode
内存检测机制造成的内存泄露问题(其实是没有内存泄露的,是个bug
),然后就是注意节点到节点本身的距离,可能通过其他节点过来的,这时 distanceThreshold
阈值可能影响结果,需要额外处理一下。代码我已经进行了详细的注释,理解应该没有问题,读者可以作为参考,如果看不懂(可以多看几遍),欢迎留言哦!我看到会解答一下。
2、问题解决
笔者以C++
方式解决。
#include "iostream"
using namespace std;
#include "algorithm"
#include "vector"
#include "queue"
#include "set"
#include "map"
#include "cstring"
#include "stack"
class Solution {
private:
// 定义邻接矩阵(存放的是在 distanceThreshold 之内的节点)
vector<vector<int>> Adu;
// 定义最大节点个数
const static int MAXV = 101;
// 定义节点个数
int n_all;
// 定义节点间距离函数,例如: dis[0][1] 代表 0 <------> 1 之间的距离
// 这里需要初始化为一个很大的距离(代表节点之间不连通)
int dis[MAXV][MAXV];
// 定义节点之间不连通距离大小
const int INF = 10001;
public:
int findTheCity(int n, vector<vector<int>> &edges, int distanceThreshold) {
// 初始化邻接矩阵
Adu.resize(n);
// 初始化节点个数
n_all = n;
// 初始化 dis 距离数组
init(edges);
// 使用佛洛依德算法 求全源最短路径
folyd();
// 根据距离数组 和 distanceThreshold 初始化邻接矩阵(存放的是在 distanceThreshold 之内的节点)
for (int i = 0; i < n_all; ++i) {
for (int j = 0; j < n_all; ++j) {
// 由于经过folyd 算法,本身的节点距离会通过其他节点在转过来形成 自己到自己的状态
// 所以需要将 自己到自己的状态 排除
if (dis[i][j] <= distanceThreshold && i != j) {
// 这里无向图仍然是双向的,会有重复的元素,但是没有关系,2*n , 可以使用 set 去重
Adu[i].push_back(j);
Adu[j].push_back(i);
}
}
}
// 结果城市
int result = 0;
// 最小城市数
int minSize = 1000;
for (int i = 0; i < n; ++i) {
// 由于需要相同值 取编号较大的值 所以这里有 等号
if (Adu[i].size() <= minSize) {
minSize = Adu[i].size();
result = i;
}
}
return result;
}
/**
*
* @param edges
*/
void init(vector<vector<int>> &edges) {
// 其实用 fill 函数初始化是最好的,但是LeetCode 会报错
/**
* Line 37: Char 29: runtime error: index 10201 out of bounds for type 'int [101]' (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:47:29
解释是:LeetCode 使用了AddressSanitizer检查是否存在内存非法访问,但是我们是二维数组,应该是一个bug
*/
// fill(dis[0], dis[0] + MAXV * MAXV, INF);
// 只能手动初始化距离数组,并将其设置成不可达的距离
for (int i = 0; i < n_all; ++i) {
for (int j = 0; j < n_all; ++j) {
dis[i][j] = INF;
}
}
// 根据题目 edges 数组,初始化 各节点的距离 0 1 2 分别代表 from to weights
for (int i = 0; i < edges.size(); ++i) {
// 因为这里是无向图 所以 a->b 的距离也是 b->a 的距离
dis[edges[i][0]][edges[i][1]] = edges[i][2];
dis[edges[i][1]][edges[i][0]] = edges[i][2];
}
}
// folyd 算法
void folyd() {
for (int k = 0; k < n_all; ++k) {
for (int i = 0; i < n_all; ++i) {
for (int j = 0; j < n_all; ++j) {
if (dis[i][k] != INF && dis[k][j] != INF && dis[i][k] + dis[k][j] < dis[i][j]) {
// 找到更短的路径
dis[i][j] = dis[i][k] + dis[k][j];
}
}
}
}
}
};
int main() {
int n = 5;
vector<vector<int>> edges = { { 0, 1, 2 },
{ 0, 4, 8 },
{ 1, 2, 3 },
{ 1, 4, 2 },
{ 2, 3, 1 },
{ 3, 4, 1 } };
int distanceThreshold = 2;
// int n = 4;
// vector<vector<int>> edges = {{0, 1, 3},
// {1, 2, 1},
// {1, 3, 4},
// {2, 3, 1}};
// int distanceThreshold = 4;
Solution *pSolution = new Solution;
int i = pSolution->findTheCity(n, edges, distanceThreshold);
cout << i << endl;
system("pause");
return 0;
}
运行结果
有点菜,有时间再优化一下。
这就是内存泄露问题.
Line 37: Char 29: runtime error: index 10201 out of bounds for type 'int [101]' (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:47:29
解释是:LeetCode
使用了AddressSanitizer
检查是否存在内存非法访问,但是我们是二维数组,应该是一个bug
3、总结
书上的代码直接运行绝大部分是对的,但是总有一些软件的更新使得作者无能为力。之前的API是对的,但是之后就废弃了或修改了是常有的事。所以我们需要跟踪源代码。这只是一个小小的问题,如果没有前辈的无私奉献,很难想象我们自己一天能学到多少内容。感谢各位前辈的辛勤付出,让我们少走了很多的弯路!
点个赞再走呗!欢迎留言哦!