Leetcode 133. Clone Graph & 138. Copy List with Random Pointer

来源:互联网 发布:大数据徐子沛 编辑:程序博客网 时间:2024/06/05 14:27

因为自己是先做的138,先说138。参考这里。

138. Copy List with Random Pointer

Total Accepted: 64859 Total Submissions: 248746 Difficulty: Hard

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

这题有两种解法。


解法一:

O(n)空间+O(n)时间。

先按照原list复制一遍,先不复制random point,这是第一遍,但是需要建立结点的对应关系,比如原来的1对应现在的1;2对应2。

然后第二遍从到到尾,新list元素的random元素即是map.get(原数组元素.random)。比如原来1.random = 3,那么当前1的random就是原来3对应的节点,用map取出。

蓝色为原始链表节点,紫红色为新链表节点:


/** * Definition for singly-linked list with a random pointer. * class RandomListNode { *     int label; *     RandomListNode next, random; *     RandomListNode(int x) { this.label = x; } * }; */public class Solution {    public RandomListNode copyRandomList(RandomListNode head) {        if(head==null) return null;        HashMap<RandomListNode, RandomListNode> hm = new HashMap<RandomListNode, RandomListNode>();        RandomListNode newHead = new RandomListNode(head.label);        hm.put(head, newHead);        RandomListNode tail = newHead;        RandomListNode cur = head.next;        while(cur!=null){            RandomListNode newcur = new RandomListNode(cur.label);            hm.put(cur, newcur);            cur = cur.next;            tail.next = newcur;            tail = tail.next;        }                cur = newHead;        while(head!=null){            cur.random = hm.get(head.random);            head = head.next;            cur = cur.next;        }        return newHead;    }}

解法二:

O(n)时间,O(1)空间。

第一遍,复制原结点。要求是将复制的点放在该结点之后,以便后来找对应的结点。比如1 -> 2 -> 3复制完变成1 -> 1-> 2-> 2-> 3-> 3->。

第二遍,复制random 指针。cur.next.random = cur.random.next。

第三遍,分离两个list。


一开始想两遍做,结果当然是不行的,因为random指针有可能指向之前的元素。

/** * Definition for singly-linked list with a random pointer. * class RandomListNode { *     int label; *     RandomListNode next, random; *     RandomListNode(int x) { this.label = x; } * }; */public class Solution {    public RandomListNode copyRandomList(RandomListNode head) {        if(head==null) return null;        RandomListNode cur = head;                while(cur.next!=null){            RandomListNode next = cur.next;            cur.next = new RandomListNode(cur.label);            cur.next.next = next;            cur = next;        }// arrive at last node        cur.next = new RandomListNode(cur.label);                cur = head;        RandomListNode newhead = head.next;        RandomListNode newcur = newhead;                while(cur!=null){            if(cur.random != null) cur.next.random = cur.random.next;              cur = cur.next.next;          }                cur = head; newcur = newhead;        while(cur!=null){            cur.next = newcur.next;            cur = cur.next;            newcur.next = cur.next;            newcur = newcur.next;        }        return newhead;    }}


133. Clone Graph

Total Accepted: 67433 Total Submissions: 271164 Difficulty: Medium

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

  1. First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
  2. Second node is labeled as 1. Connect node 1 to node 2.
  3. 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         / \         \_/



感觉这类复制题,都是加一些额外的限制。比如138题有random的限制,你需要找对应关系。

而这道题,也一样加了限制,就是每个点相连的点有可能重复。也就是说仍然需要对应关系来知道这个点是否已经存在。

参考自code ganker:http://blog.csdn.net/linhuanmars/article/details/22715747

思路:

1. BFS。每次取一个点。然后check table中有没有这个点的key,如果有,说明已经创建过了,只需要更新入结点的neighbor就行了;如果没有则创建之,映射关系存入map,并加入queue待下次遍历其neighbor。

/** * Definition for undirected graph. * class UndirectedGraphNode { *     int label; *     List<UndirectedGraphNode> neighbors; *     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); } * }; */public class Solution { // BFS    public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {        if(node==null) return null;        HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();        LinkedList<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>();        UndirectedGraphNode newnode = new UndirectedGraphNode(node.label);        map.put(node, newnode);        queue.add(node);                while(queue.size()!=0){            UndirectedGraphNode cur = queue.poll();            for(UndirectedGraphNode neighbor : cur.neighbors){                if(!map.containsKey(neighbor)){                    newnode = new UndirectedGraphNode(neighbor.label);                    map.put(neighbor, newnode);                    queue.add(neighbor);                }                map.get(cur).neighbors.add(map.get(neighbor));            }        }        return map.get(node);    }}

2.DFS。

跟BFS的不同是,BFS是遇到一个没访问过的点,则创建之并加入队尾,每次取队首元素,这样就先遍历了所有该结点的邻居,再从邻居出发遍历。

DFS则是每次取队尾元素。

/** * Definition for undirected graph. * class UndirectedGraphNode { *     int label; *     List<UndirectedGraphNode> neighbors; *     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); } * }; */public class Solution { // DFS     public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {        if(node==null) return null;        HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();        LinkedList<UndirectedGraphNode> stack = new LinkedList<UndirectedGraphNode>();        UndirectedGraphNode newnode = new UndirectedGraphNode(node.label);        map.put(node, newnode);        stack.push(node);                while(stack.size()!=0){            UndirectedGraphNode cur = stack.pop();            for(UndirectedGraphNode neighbor : cur.neighbors){                if(!map.containsKey(neighbor)){                    newnode = new UndirectedGraphNode(neighbor.label);                    map.put(neighbor, newnode);                    stack.push(neighbor);                }                map.get(cur).neighbors.add(map.get(neighbor));            }        }        return map.get(node);    }}

DFS用递归实现:

碰到新节点,创建,入map,然后立即调用helper。

/** * Definition for undirected graph. * class UndirectedGraphNode { *     int label; *     List<UndirectedGraphNode> neighbors; *     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); } * }; */public class Solution { // DFS recursive     public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {        if(node==null) return null;        HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();        UndirectedGraphNode newnode = new UndirectedGraphNode(node.label);        map.put(node, newnode);        helper(node, map);        return map.get(node);    }            void helper(UndirectedGraphNode node, HashMap<UndirectedGraphNode, UndirectedGraphNode> map){        for(UndirectedGraphNode neighbor : node.neighbors){                if(!map.containsKey(neighbor)){                    UndirectedGraphNode newnode = new UndirectedGraphNode(neighbor.label);                    map.put(neighbor, newnode);                    helper(neighbor, map);                }                map.get(node).neighbors.add(map.get(neighbor));        }    }}


所有方法的时间复杂度和空间复杂度都是O(n)。


0 0
原创粉丝点击