input:算法
n
// 表明無向圖的頂點數 // 從1開始m
// 無向圖的邊數arr1
// 各邊的狀況,形如[[1, 2], [3, 4],...]
(表明頂點0和頂點2相連,頂點3和頂點4相連)arr2
// 但願求得的連通狀況數組,形如[[1, 3], [1, 4], ...]
(表明但願知道頂點1,頂點3的連通狀況,頂點1和頂點4的連通狀況)output:
num
,arr2
中能夠連通的數量數組示例: input:code
n = 3
m = 1
arr1 = [[1, 3]]
arr2 = [[2, 3]]
output:
0
leetcode
下面是我解決這個題的時候的思路input
這個題,剛拿到的時候,我最初的想法是使用無向圖的鄰接矩陣,而後在檢查點的時候經過廣度優先遍歷查看兩個點是否連通。實現這個想法以後就發現,時間複雜度真的過高了。每一次都會產生許多的無用查詢。hash
而後我想了另一個思路,既然只查詢兩個點是否連通,那麼咱們維護一個連通集合不就能夠了。一開始每個孤立的點都是一個單獨的連通集合,形如['1', '2', '3', '4']
,在加上一條邊以後,就是該邊的兩個頂點所在的連通集合合併成同一個連通集合,即加上邊[1, 3]
後,連通集合變成['13', '2', '4']
。這樣,在查詢的時候,去尋找頂點B是否在頂點A所處的連通集合裏就能夠了。因而我寫出了以下的代碼。io
function solution(n, m, arr1, arr2) { let hash = new Array(n + 1) // 表明每一個點的所在的連通集合,undefined表明這個點還不與其餘點相連,0位無效 let map = {} // 保留每一個聯通集合的點集 let index = 1 // 下一個聯通集合的編號 for (let i = 0; i < m; i++) { // 依次添加邊到連通集合裏 let edge = arr1[i] let A = edge[0] // 頂點A let B = edge[1] // 頂點B if (hash[A] === undefined && hash[B] === undefined) { // 這兩個都是孤立的點,新建一個連通集合 hash[A] = index hash[B] = index map[index++] = [A, B] } else if (hash[B] === undefined) { // 點A不是孤立的,點B是孤立的,把B加入A的連通集合裏 hash[B] = hash[A] map[hash[A]].push(B) } else if (hash[A] === undefined) { // 點B不是孤立的,點A是孤立的,把A加入B的連通集合裏 hash[A] = hash[B] map[hash[B]].push(A) } else if (hash[A] !== hash[B]) { // A,B均不是孤立的,把B的連通集合,加入A的連通集合裏 B_list = map[hash[B]] // B所在的連通集合的頂點列表 group = hash[A] for (let i = B_list.length - 1; i >= 0; i--) { // 每一個頂點的連通集合修改成A的 hash[B_list[i]] = group } map[group] = map[group].concat(map[hash[B]]) delete map[hash[B]] } } let result = 0 // 連通的數量 for (let i = arr2.length - 1; i >= 0; i--) { let test = arr2[i] let groupA = hash[test[0]] let groupB = hash[test[1]] if (groupA && groupB && groupA === groupB) { result++ } } return result }
也就是,用hash來存放對應的點所在的連通集合,map存放連通集合對應的點。function
本期算法小分享就到這裏咯(leetcode剛作完探索裏的初級,還有好多已經說爛了的題就不分享了。)若是有什麼意見或者想法歡迎在評論區和我交流test