[LeetCode] Clone Graph(!!!!graph&dfs&bfs)

Clone Graph

Clone an undirected graph. Each node in the graph contains a label and
a list of its neighbors.

OJ’s undirected graph serialization: Nodes are labeled uniquely.

We use # as a separator for each node, and , as a separator for node
label and each neighbor of the node. As an example, consider the
serialized graph {0,1,2#1,2#2,2}.

The graph has a total of three nodes, and therefore contains three
parts as separated by #.

First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
Second node is labeled as 1. Connect node 1 to node 2. Third node is
labeled as 2. Connect node 2 to node 2 (itself), thus forming a
self-cycle. Visually, the graph looks like the following:

   1
  / \
 /   \
0 --- 2
     / \
     \_/

LeetCode中比较少的图的题目,图是采用邻接链表的方式存储的。每一个节点的结构体包含两个成员,一个是label属性,一个是相邻节点的链表。
还要建立一个源节点和拷贝节点的映射,目的是我们无论是dfs还是bfs找到每一个节点都建立一个与它label相同的拷贝节点。将这组对应关系存到map中去。
对于一个新的节点curr,我们在map中找它的所有邻接节点neighb。如果没找到,说明是第一次访问它,把它加入map中去,也放到队列中去。如果找到了,说明它在之前被访问过了,同时说明它是之前队列中节点的邻接节点,这时将这个找到的map[neighb]加入curr的neighbors里。

class Solution{
public:
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node){
        if(node==NULL)  return NULL;
        //key为所有不重复节点的,value为这个节点对应copy版本
        unordered_map<UndirectedGraphNode *, UndirectedGraphNode *> nodeMap;
        queue<UndirectedGraphNode *> visit;          //bfs用于保存节点
        visit.push(node);
        UndirectedGraphNode *nodeCopy = new UndirectedGraphNode(node->label);
        nodeMap[node] = nodeCopy;
        while(visit.size()>0)
        {
            UndirectedGraphNode *curr = visit.front();
            visit.pop();
            //bfs,对于每一个相邻的节点
            for(int i = 0; i < curr->neighbors.size(); ++i)
            {
                UndirectedGraphNode *neighb = curr->neighbors[i];
                if(nodeMap.find(neighb)==nodeMap.end())//没有访问过
                {
                    UndirectedGraphNode* neighbCopy = new UndirectedGraphNode(neighb->label);
                    nodeMap[neighb] = neighbCopy;//将这个没有访问过的节点和拷贝节点放到map中
                    visit.push(neighb); //bfs放入队列
                    nodeMap[curr]->neighbors.push_back(neighbCopy);//copy的部分
                }
                else//这个节点访问过,是其他节点的相邻节点
                    nodeMap[curr]->neighbors.push_back(nodeMap[neighb]);

            }
        }
        return nodeCopy;
    }
};

76ms AC

这里再回顾下bfs和dfs的实现,以二叉树的遍历为例

//bfs或层序遍历
void LevelOrderTraversal(BinTree BT){
    queue<BinTree> q;
    BinTree T;
    if(!BT) return ;  //树为空
    q.push(BT);
    while(!q.empty()){
        T = q.front();
        q.pop();
        cout<<T->Data<<endl;
        //处理T邻接点
        if(T->left) q.push(T->left);
        if(T->right) q.push(T->right);
    }

}
//dfs或是中序遍历递归实现
void InorderTraversal(BinTree BT){
    if(BT){
        InorderTraversal(BT->left);
        cout <<BT->data<<endl;
        InorderTraversal(BT->Right);
    }

}
//dfs或中序遍历的非递归实现
void InorderTraversal(BinTree BT){
    BinTree T= BT;
    stack<BinTree> sta;
    while(!sta.empty()||T){
        while(T){    //一直向左压栈
            sta.push(T);
            T = T->left;
        }
        T = sta.top();
        sta.pop();
        cout<<T->data<<endl;
        T= T->right;
    }
}

这样cloneGraph这道题用dfs

class Solution{
public:
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node){
        if(node==NULL) return NULL;
        stack<UndirectedGraphNode> sta;  //dfs用的栈
        unordered_map<UndirectedGraphNode *, UndirectedGraphNode *> nodeMap; 
        UndirectedGraphNode * nodeCopy = new UndirectedGraphNode(node->label);
        nodeMap[node] = nodeCopy;
        sta.push(node);
        while(!sta.empty())
        {
            UndirectedGraphNode * curr = sta.top();
            sta.pop();//栈顶元素
            for(int i = 0; i <curr->neighbors.size(); ++i)
            {
                UndirectedGraphNode * neighb = curr->neighbors[i];
                if(nodeMap.find(neighb)==nodeMap.end())//没有访问过
                {
                    UndirectedGraphNode * neighbCopy = new UndirectedGraphNode(neighb->label);
                    nodeMap[neighb] = neighbCopy;
                    sta.push(neighb);
                }
                nodeMap[curr]->neighbors.push_back(nodeMap[neighb]);
            }
        }
        return nodeCopy;
    }
};

164ms AC好慢。。

dfs和bfs在这道题上的效率差别还是很明显的,bfs明显比dfs快很多。

所以重新按照这道题的通用思路还写一下二叉树的dfs或bfs的通用版本

void bfs(BinTree BT){
    queue<BinTree> q;
    q.push(BT);
    while(!q.empty()){
        BinTree T = q.front();
        q.pop();
        cout<<T;//作为访问T
        if(!T->left)
            q.push(T->left);
        if(!T->right)
            q.push(T->right);

    }
}
void dfs(BinTree BT){
    stack<BinTree> sta;
    sta.push(BT);
    while(!sta.empty()){
        BinTree T = sta.top();
        sta.pop();
        cout<<T;
        if(!T->right)
            sta.push(T->right);
        if(!T->left)
            sta.push(T->left);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值