[C ++] LeetCode: 129 Clone Graph (deep copy BFS & amp; DFS of the Graph)

Source: Internet
Author: User

[C ++] LeetCode: 129 Clone Graph (deep copy BFS & amp; DFS of a Graph)

Question:

Clone an undirected graph. Each node in the graph containslabelAnd a list of itsneighbors.


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#.

  1. First node is labeled0. Connect node0To both nodes1And2.
  2. Second node is labeled1. Connect node1To node2.
  3. Third node is labeled2. Connect node2To node2(Itself), thus forming a self-cycle.

    Visually, the graph looks like the following:

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

    Background:

    1. Deep copy and light copy

    (1) Deep copy means that the source object and the copy object are independent of each other. Any changes to one object will not affect the other object. For example, a person named Zhang San was cloned with him (assuming the law permits it) and called Li Si. Neither Zhang San's arm nor legs nor Li Si's arm nor legs would affect another person. Typical objects are Value objects, such as Int32, Double, struct, and Enum.

    Consider the following statement:

    Int source = int. MaxValue; // (1) initialize the maximum value of the source object as an integer: 2,147,483,647

    Int dest = source; // (2) assign a value and execute deep copy internally.

    Dest = 1024; // (3) assign values to the Copied object

    Source = 2048; // (4) assign values to the source object

    First (2) Assign source to dest and execute the deep copy action. At that time, the values of dest and source are the same, both of which are int. maxValue; (3) modify the dest, and the value of dest changes to 1024. Because it is a deep copy, the source is not run, and the source is still int. maxValue; (4) the source is modified. Similarly, dest is still 1024, and int. the value of MaxValue remains unchanged, which is still 2,147,483,647; only source is changed to 2048.

    (2) shallow copy refers to the sharing of an object between the source object and the copy object. It only means that the referenced variables are different (different names ). Any changes to one of the objects will affect another object. For example, a person was originally named Zhang San and later renamed Li Si, but he was still the same person. Whether Zhang San lacks his arm and legs or Li Si lacks his arm and legs, this person is unlucky. A typical example is a Reference object, such as a Class ).

    Consider the following statement:

    Class Point

    {

    Public int X;

    Public int Y;

    Public Point (int x, int y)

    {

    X = x;

    Y = y;

    }

    }

    Point source = new Point (10, 20 );

    Point dest = source;

    Dest. X = 20;

    Because Point is now a reference object, the value assignment of Point dest = source actually executes a shortest copy, and the final result should be that the value of source's X field has also changed to 20. That is to say, they reference the same object, but the variables are different from those of 'source' and 'dest.

    2. Data Structure and structure pointer

    (1) Data Structure: If the structure definition includes the model_name parameter (optional), this parameter becomes a valid type name equivalent to this structure. For example:

    Struct products {
    Char name [30];
    Float price;
    };
    Products apple;
    Products orange, melon;

    We first define the structure module products, which contains two domains: name and price, each of which is a different data type. Then we declare three objects of this type using the name of this structure type (products): apple, orange, and melon.

    After we declare three objects (apple, orange, and melon) that determine the structure model, we can operate on each of their fields, this inserts a symbolic dot (.) between the Object Name and domain name (.). For example, we can operate the following elements like using standard variables:

    Apple. name
    Apple. price
    Orange. name
    Orange. price
    Melon. name
    Melon. price (2) Data Structure pointer:

    Like other data types, the structure can also have pointers. The rule is the same as other basic data types: the pointer must be declared as a pointer pointing to the structure:

    Struct movies_t {
    Char title [50];
    Int year;
    };
    Movies_t amovie;
    Movies_t * pmovie;

    Here, amovie is an object of the Structure Type movies_t, and pmovie is a pointer to the object of the Structure Type movies_t. Therefore, like the basic data type, the following expressions are correct:

    pmovie = &amovie;

    The above Code introduces an important OPERATOR:->. This is a reference operator, which is often used with pointers of structures or classes to reference member elements. This avoids many parentheses. For example, we use:

    pmovie->title

    To replace:

    (*pmovie).title

    The above two expressions, pmovie-> title and (* pmovie). title, are both valid and indicate the value of the element title in the structure pointed to by the pointer pmovie. We need to clearly distinguish it from the following expressions:

    *pmovie.title

    It is equivalent

    *(pmovie.title)

    This expression is meaningless in this example because the title itself is not a pointer type.

    The following table summarizes various possible combinations of pointers and structures:

    Expression Description Equivalent
    Pmovie. title Element title of structure pmovie
    Pmovie-> title The value of the element title in the structure pointed to by the pointer pmovie (* Pmovie). title
    * Pmovie. title The element title of the structure pmovie is the value pointed to by the pointer. * (Pmovie. title)
    Nested structure (Nesting structures)

    The structure can be nested, that is, the element of a structure itself can be another structure type. For example:

    Struct movies_t {
    Char title [50];
    Int year;
    }

    Struct friends_t {
    Char name [50];
    Char email [50];
    Movies_t favourite_movie;
    } Charlie, maria;

    Friends_t * pfriends = & charlie;

    Therefore, after the preceding Declaration, we can use the following expression:

    Charlie. name
    Maria. favourite_movie.title
    Charlie. favourite_movie.year
    Pfriends-> favourite_movie.year

    (The last two expressions are equivalent)


    Ideas:The requirement of the question is to make a deep copy of the image. Deep copy refers to copying another object to its own object, and the two do not share a memory zone. The light copy refers to sharing a memory zone between the two. So we need new to open up a new memory zone for copying. Pay attention to one problem. Our graph is actually A directed graph. If A has an adjacent vertex B, A-> B, but whether B can reach A depends on whether B has an adjacent vertex. that is to say, if B can reach A, it indicates that there is A ring in the figure. If the existence of the ring is not considered, an endless loop may be formed in the copy process.


    Assume that we copy A (A2) from the vertex A of the graph and find that A has an adjacent vertex B, then copy it to B (B2), then link A2-> B2, this makes B2 an adjacent vertex of A2. Next, we operate B and find that B has an adjacent vertex A, and A has been copied. If we copy A again, an endless loop will be formed. All we need to do is to connect B2-> A2. How can we avoid this copy again? We only need a map. Every time we make a copy, we put it into the map. Next time we query, if there is an existing copy, we will not continue copying, just connecting. If not, copy the data, connect it, and put the key of map. map to the original vertex. The value is the copy version of the original point. <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHA + vt/M5b3iys2/5E + CjxwPm1hcNbQtcRrZXksdmFsdWW31rHwsaO05mNvcHm5/fingerprint Examples/examples + CjxwPjxzdHJvbmc + examples + PHN0cm9uZz7W99Kqyse7 + bG + t723qLXEstnX98rHt/examples + bG + stnX97XE1 + m6 Z6OsyN3S17vsz/2jrNOmuMPX0M + 40dC + v8/CtPrC66GjPC9zdHJvbmc + modules + bG + modules/ujvw = "->" or ". "You can also clearly identify the object to be operated, and then decide which method to call and operate in C ++.

    CurClone-> neighbors. push_back (neighborClone); // Add the copied neighbor to curClone.

    2. Note that during the copy process, we always need to copy the original node. When dealing with the connection relationship, we also need to connect between the copy versions.

    CurClone-> neighbors. push_back (neighborClone); // Add the copied neighbor to curClone.

    3. Add a pair to map and add "{}".

    Cmap. insert ({neighbor, neighborClone}); // Add to map

    Complexity: O (N), because every node is accessed. The space complexity is that the size of the stack or queue plus the map will not exceed O (N ).

    AC Code: (BFS)

    /*** Definition for undirected graph. * struct UndirectedGraphNode {* int label; * vector
       
        
    Neighbors; * UndirectedGraphNode (int x): label (x) {}; *}; */class Solution {public: UndirectedGraphNode * cloneGraph (UndirectedGraphNode * node) {if (node = NULL) return NULL; // open up a new storage space copy UndirectedGraphNode * copy = new UndirectedGraphNode (node-> label); // find the map unordered_map to be reused
        
         
    Place the original node and Its Replica unordered_map
         
          
    Cmap; // The stored queue for BFS queue
          
           
    GraphQ; graphQ. push (node); // Add the root node to the queue cmap. insert ({node, copy}); // put the root node and its replica into map while (! GraphQ. empty () {UndirectedGraphNode * cur = graphQ. front (); // The current processing object graphQ. pop (); UndirectedGraphNode * curClone = cmap [cur]; // replica of the current processing object because it has been created in the previous neighbor // determine each neighbor of the current vertex, because some neighbor has been copied, some do not have for (int I = 0; I <cur-> neighbors. size (); I ++) {UndirectedGraphNode * neighbor = cur-> neighbors [I]; // if you have not copied if (cmap. find (neighbor) = cmap. end () {UndirectedGraphNode * neighborClone = new UndirectedGraphNode (neighbor-> label); curClone-> neighbors. push_back (neighborClone); // Add the copied neighbor cmap to curClone. insert ({neighbor, neighborClone}); // Add graphQ to map. push (neighbor); // Add to the queue for future traversal} else // The neighbor {UndirectedGraphNode * neighborClone = cmap [neighbor] that has been copied before; // extract the previous copy version curClone from map-> neighbors. push_back (neighborClone); // Add the copied neighbor to curClone }}return copy ;}};
          
         
        
       


    AC Code: (DFS)

    Replace the storage with the stack storage node to get a deep search priority.

    /*** Definition for undirected graph. * struct UndirectedGraphNode {* int label; * vector
       
        
    Neighbors; * UndirectedGraphNode (int x): label (x) {}; *}; */class Solution {public: UndirectedGraphNode * cloneGraph (UndirectedGraphNode * node) {if (node = NULL) return NULL; stack
        
         
    Stk; unordered_map
         
          
    Cmap; UndirectedGraphNode * copy = new UndirectedGraphNode (node-> label); stk. push (node); cmap. insert ({node, copy}); while (! Stk. empty () {UndirectedGraphNode * cur = stk. top (); stk. pop (); UndirectedGraphNode * curClone = cmap [cur]; // for shortest, the start vertex curClone and copy point to the same address for (int I = 0; I <cur-> neighbors. size (); I ++) {UndirectedGraphNode * neighbors = cur-> neighbors [I]; if (cmap. find (neighbors) = cmap. end () {UndirectedGraphNode * neighborsClone = new UndirectedGraphNode (neighbors-> label); curClone-> neighbors. push_back (neighborsClone); cmap. insert ({neighbors, neighborsClone}); stk. push (neighbors);} else {UndirectedGraphNode * neighborsClone = cmap [neighbors]; curClone-> neighbors. push_back (neighborsClone) ;}} return copy ;}};
         
        
       
    The two traversal methods shown in the figure are classic problems. Although there are not many in the interview, they may still appear. When there is a problem, you must do a good job. Therefore, you must master this question carefully. It is best to write it several times to investigate the basic operations.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.