首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

單詞鏈接問題:判斷能否排序成首尾相連環(C語言實作)

     編輯:關於C語言

問題描述

給定 N 個單詞(1 <= N <= 10000,每詞長 ≤ 100,僅小寫字母)。判斷是否能重新排序這些單詞,使得每個單詞的首字母等於前一個單詞的尾字母。輸出 "Possible" 或 "Impossible"。

範例:

輸入: 2  ok  ok        → Impossible (o→k, o→k 無法連接)
輸入: 2  ok  ko        → Possible   (o→k, k→o 可成環)

圖論建模:歐拉路徑判定

將 26 個小寫字母視為圖的節點,每個單詞是一條有向邊:從首字母指向尾字母。問題轉化為:該有向圖是否存在歐拉路徑(或歐拉迴路)?

有向圖存在歐拉路徑的充要條件:

  1. 圖是弱連通的(忽略方向後連通)。
  2. 入度等於出度的節點數為 26、或 24(其餘兩節點一個出度=入度+1 為起點,一個入度=出度+1 為終點)。

原碼採用貪心嘗試連接,未嚴格檢查連通性與度數條件,可能對某些案例誤判。下面給出正確的歐拉路徑判定實作。

正確演算法實作(C 語言)

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#define MAX_WORDS 10000
#define MAX_LEN 100

int main() {
    int N;
    while (scanf("%d", &N) == 1) {
        int in[26] = {0}, out[26] = {0};
        int parent[26];
        for (int i = 0; i < 26; i++) parent[i] = i;  // 並查集初始化

        char word[MAX_LEN + 1];
        for (int i = 0; i < N; i++) {
            scanf("%s", word);
            int u = word[0] - 'a';
            int v = word[strlen(word) - 1] - 'a';
            out[u]++; in[v]++;

            // 並查集合併(無向連通性)
            auto find = [&](int x) {
                while (parent[x] != x) x = parent[x] = parent[parent[x]];
                return x;
            };
            int ru = find(u), rv = find(v);
            if (ru != rv) parent[ru] = rv;
        }

        // 條件 1:弱連通(所有有邊節點屬於同一連通分量)
        int comp = -1;
        bool connected = true;
        for (int i = 0; i < 26; i++) {
            if (in[i] || out[i]) {
                int r = find(i);
                if (comp == -1) comp = r;
                else if (comp != r) { connected = false; break; }
            }
        }

        // 條件 2:度數平衡
        int start = 0, end = 0;
        bool degree_ok = true;
        for (int i = 0; i < 26; i++) {
            if (out[i] == in[i] + 1) start++;
            else if (in[i] == out[i] + 1) end++;
            else if (in[i] != out[i]) { degree_ok = false; break; }
        }
        degree_ok = degree_ok && ((start == 0 && end == 0) || (start == 1 && end == 1));

        printf("%s\n", (connected && degree_ok) ? "Possible" : "Impossible");
    }
    return 0;
}

關鍵點解析

步驟說明
建圖單詞 → 有向邊 (首字母→尾字母),統計入/出度。
連通性並查集維護無向連通分量,僅檢查有邊節點是否同一分量。
度數條件歐拉迴路:所有節點入=出;歐拉路徑:恰一起點(out=in+1)、一終點(in=out+1)。
複雜度O(N * L + 26) ≈ O(N),L 為平均單詞長度,極高效。

常見誤區

  • 原碼嘗試「貪心連接並標記已用」,但未處理「多連通分量」與「度數不平衡」的根本判定,易產生假陽性/陰性。
  • 忽略「弱連通」條件:如 ab, bc, cd, de, fg, gh 兩條不相連鏈,度數雖平衡但無法串成單一序列。
  • 未處理重邊(相同單詞多次出現):入出度計數自動處理,並查集合併冪等,無影響。

結語

單詞鏈接問題是「有向圖歐拉路徑判定」的經典應用。掌握「入出度平衡 + 弱連通」兩大核心條件,即可在 O(N) 時間內精準求解。此模型廣泛應用於基因組裝(De Bruijn 圖)、郵遞員路徑規劃、電路板走線等領域。建議進一步學習 Hierholzer 演算法實際構造歐拉路徑序列。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved