Leetcode 1334. 閾值距離內鄰居最少的城市

Leetcode 1334. 閾值距離內鄰居最少的城市

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

點個贊再走唄!歡迎留言哦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章