LeetCode685.冗餘連接II

在本問題中,有根樹指滿足以下條件的有向圖。該樹只有一個根節點,所有其他節點都是該根節點的後繼。每一個節點只有一個父節點,除了根節點沒有父節點。

輸入一個有向圖,該圖由一個有着N個節點 (節點值不重複1, 2, ..., N) 的樹及一條附加的邊構成。附加的邊的兩個頂點包含在1到N中間,這條附加的邊不屬於樹中已存在的邊。

結果圖是一個以邊組成的二維數組。 每一個邊 的元素是一對 [u, v],用以表示有向圖中連接頂點 u and v和頂點的邊,其中父節點u是子節點v的一個父節點。

返回一條能刪除的邊,使得剩下的圖是有N個節點的有根樹。若有多個答案,返回最後出現在給定二維數組的答案。

示例 1:

輸入: [[1,2], [1,3], [2,3]]
輸出: [2,3]
解釋: 給定的有向圖如下:
  1
 / \
v   v
2-->3

示例 2:

輸入: [[1,2], [2,3], [3,4], [4,1], [1,5]]
輸出: [4,1]
解釋: 給定的有向圖如下:
5 <- 1 -> 2
     ^    |
     |    v
     4 <- 3

注意:

    二維數組大小的在3到1000範圍內。
    二維數組中的每個整數在1到N之間,其中 N 是二維數組的大小。

鏈接:https://leetcode-cn.com/problems/redundant-connection-ii

【思路】

684. 冗餘連接不同,這一題是有向圖,我們判斷圖中是否存在環的同時,需要判斷是否存在重複的父節點。

因爲題目中必須要刪除一條邊,因此不存在既沒有環又沒有重複父節點的情況。

分三種情況:

1)[[1,2], [1,3], [2,3]]

加入邊[2,3]後,節點3存在重複節點1和2

2)[[1,2], [2,3], [3,4], [4,1], [1,5]]

加入節點[4,1]之後,出現

3)[[2,1],[3,1],[4,2],[1,4]]

加入[3,1]後,節點1出現重複節點2和3;加入[1,4]後,同時出現環

我們先判斷圖中是否存在重複節點,如果存在重複節點,那麼相鄰的兩條邊必須要刪除其中一條,我們可以假設先刪除一條,緊接着再判斷下刪除後的圖中是否有環即可,如果有,那麼應該刪除另外一條。例如上述3,當節點1出現重複節點的時候,可以刪除[3,1]或者[2,1],假設我們刪除[3,1],然而刪除後圖中存在環,那麼答案應該刪除[2,1]。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int set[1000000];
int find(int u){//找父節點,由於是有向樹,那麼不要用壓縮路徑,找直系父節點
    return u==set[u]?u:find(set[u]);
}
int* findRedundantDirectedConnection(int** edges, int edgesSize, int* edgesColSize, int* returnSize){
    int i,j;
    int u,v;
    int last=-1,tmp=-1,*first=(int*)malloc(sizeof(int)*2),*second=(int*)malloc(sizeof(int)*2);
//以下代碼判斷是否存在重複節點,如果有重複節點,那麼刪除的一定在引起重複節點的兩條邊中。我們標記這兩條邊爲first和second
    for(i=1;i<=edgesSize;i++){
        set[i]=i;
    }
    for(i=0;i<edgesSize;i++){//判斷是否有重複的父節點
        u=edges[i][0];
        v=edges[i][1];
        if(set[v]!=v&&u!=set[v]){
            first[0]=set[v];first[1]=v;
            second[0]=u;second[1]=v;
            tmp=i;
            break;
        }else{
            set[v]=u;//v的父節點爲u
        }
    }
//這裏我們假設刪除second,查看刪除後是否存在環,如果不存在環,那麼刪除second是對滴,否則刪除first
//和上一題類似,查看刪除second後是否存在環,這邊唯一需要注意的是,和無向圖不同,有向圖中父節點(除了根節點)只有一個,因此對於[u,v],直接賦值set[v]=u;即可。
    for(i=1;i<=edgesSize;i++){
        set[i]=i;
    }
    for(i=0;i<edgesSize;i++){  
        if(i==tmp)continue;
        u=edges[i][0];
        v=edges[i][1];
        if(find(u)==find(v)){//存在環
            last=i;
        }else{
            set[v]=u;//直接賦值
        }
    }
    *returnSize=2;
    //判斷三種情況
    if(tmp!=-1&&last==-1)//存在重複節點,且刪除second之後,不存在環
        return second;
    else if(tmp!=-1&&last!=-1)//存在重複節點且刪除second之後還存在環,此時不應該刪除second,刪除
        return first;
    //不存在重複節點,但存在環
    return edges[last]; 
}

 

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