在Java的面試中,最小生成樹(shù)是一個(gè)常見(jiàn)的算法主題。本文將介紹一道經(jīng)典的Java面試題——最小生成樹(shù),并提供詳細(xì)的解析和解題思路。
題目
給定一個(gè)帶權(quán)無(wú)向圖,找到一棵包含所有節(jié)點(diǎn)的最小生成樹(shù)。
解析與解題思路
最小生成樹(shù)是一個(gè)圖論中的重要概念,指的是在無(wú)向圖中找到一棵生成樹(shù),使得所有邊的權(quán)值之和最小。
在解決最小生成樹(shù)問(wèn)題時(shí),我們可以使用貪心算法中的Prim算法或Kruskal算法。
- Prim算法:
首先,我們隨機(jī)選擇一個(gè)節(jié)點(diǎn)作為起始節(jié)點(diǎn),將其加入到最小生成樹(shù)中,并將其標(biāo)記為已訪問(wèn)。
然后,我們從已訪問(wèn)的節(jié)點(diǎn)集合中選取一個(gè)節(jié)點(diǎn),該節(jié)點(diǎn)到未訪問(wèn)的節(jié)點(diǎn)的邊權(quán)值最小,將這個(gè)邊和對(duì)應(yīng)的未訪問(wèn)節(jié)點(diǎn)加入到最小生成樹(shù)中。
不斷重復(fù)上述步驟,直到所有節(jié)點(diǎn)都被訪問(wèn)。 - Kruskal算法:
首先,我們將所有邊按照權(quán)值從小到大進(jìn)行排序。
然后,從權(quán)值最小的邊開(kāi)始遍歷,如果這條邊的兩個(gè)節(jié)點(diǎn)不在同一個(gè)連通分量中,就將這條邊加入到最小生成樹(shù)中,并將這兩個(gè)節(jié)點(diǎn)合并到同一個(gè)連通分量中。
不斷重復(fù)上述步驟,直到最小生成樹(shù)中包含了所有節(jié)點(diǎn)。
通過(guò)Prim算法或Kruskal算法,我們可以找到一個(gè)包含所有節(jié)點(diǎn)的最小生成樹(shù)。
以下是Java代碼實(shí)例(使用Prim算法):
import java.util.Arrays;
public class MinimumSpanningTree {
public static int primMST(int[][] graph) {
int n = graph.length;
int[] key = new int[n]; // 存儲(chǔ)節(jié)點(diǎn)到最小生成樹(shù)的最小權(quán)值
boolean[] visited = new boolean[n]; // 記錄節(jié)點(diǎn)是否已訪問(wèn)
Arrays.fill(key, Integer.MAX_VALUE);
key[0] = 0; // 選擇第一個(gè)節(jié)點(diǎn)作為起始節(jié)點(diǎn)
int minCost = 0;
for (int i = 0; i < n; i++) {
int u = -1; // 用于存儲(chǔ)當(dāng)前的最小權(quán)值節(jié)點(diǎn)
for (int v = 0; v < n; v++) {
if (!visited[v] && (u == -1 || key[v] < key[u])) {
u = v;
}
}
visited[u] = true;
minCost += key[u];
for (int v = 0; v < n; v++) {
if (!visited[v] && graph[u][v] != 0 && graph[u][v] < key[v]) {
key[v] = graph[u][v];
}
}
}
return minCost;
}
public static void main(String[] args) {
int[][] graph = {
{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0}
};
int minCost = primMST(graph);
System.out.println("最小生成樹(shù)的權(quán)值之和為:" + minCost);
}
}
結(jié)論
通過(guò)Prim算法或Kruskal算法,我們可以找到一個(gè)包含所有節(jié)點(diǎn)的最小生成樹(shù)。最小生成樹(shù)是面試中常見(jiàn)的算法題目,掌握了解題思路和實(shí)現(xiàn)代碼,我們能夠在面試中更加自信地回答相關(guān)問(wèn)題。
學(xué)java,就到java編程獅!