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是對的,但是之後就廢棄了或修改了是常有的事。所以我們需要跟蹤源代碼。這只是一個小小的問題,如果沒有前輩的無私奉獻,很難想象我們自己一天能學到多少內容。感謝各位前輩的辛勤付出,讓我們少走了很多的彎路!
點個贊再走唄!歡迎留言哦!