剑指offer第二版——面试题35(java)

面试题:复杂链表的复制

题目:

实现函数,复制一个复杂链表,链表中,每个节点除了有一个next指针指向下一个节点,还有一个sibling指针指向链表中的任意节点或nullptr

思路:

(全是书上写的 我啥也没想出来QAQ)

先提到了两种思路,一个是:先复制主路线,即用next连接的部分,再复制sibling,但是这样每个结点的sibling都需要从头开始寻找,时间复杂度太高;另一个是:用哈希表存储,需要消耗空间

从【对每个结点寻找其sibling时间复杂度】太高这个角度来寻找优化方法。

使用的方法:

先复制主路线,但是每个结点的clone结点就直接接在原结点后面,如A-A'-B-B'-C-C'-D-D',再根据原始结点的sibling对clone结点进行连接,如果A的sibling是C,可见A'的sibling是C',此时C'在C之后,可以直接用A.sibling.next获取C',不需要额外进行查找,最后把两个链表分开即可

分成三步完成:

① 复制主路线

② 连接sibling

③ 分开两个链表

【代码】

public class Q35 {
	public static void main(String[] args) {
		ComplexNode head = getLink();
		clone(head);
		addSibling(head);
		ComplexNode clone = devideLink(head);
		showLink(clone);
		showLink(head);
	}
	
	// 步骤一:复制主路线
	public static void clone(ComplexNode head) {
		while(head!=null) {
			ComplexNode temp = new ComplexNode(head.val);
			temp.next = head.next;
			head.next = temp;
			head = temp.next;
		}
	}
	
	// 步骤二:添加sibling
	public static void addSibling(ComplexNode head) {
		while(head!=null) {
			if(head.sibling!=null) {
				head.next.sibling = head.sibling.next;
			}
			head = head.next.next;	
		}
	}
	
	// 步骤三:分开两个链表
	public static ComplexNode devideLink(ComplexNode head) {
		if(head==null) {
			return null;
		}
		
		ComplexNode save_head = head;
		ComplexNode save_clone = head.next;
		ComplexNode head_o,head_c;
				
		int flag = 0;
		head_o = head;
		head_c = head.next;
		ComplexNode temp = head_c.next;
		while(temp!=null) {
			if(flag%2==1) {
				head_o.next = temp;
				head_o = temp;
			}else {
				head_c.next = temp;
				head_c = temp;
			}
			flag++;
			temp = temp.next;
		}
		head_c.next = null;
		head_o.next = null;
		
		head = save_head;
		return save_clone;
	}
	
	
	// 构造复杂链表
	public static ComplexNode getLink() {
		ComplexNode node4 = new ComplexNode(4);
		ComplexNode node1 = new ComplexNode(1);
		ComplexNode node2 = new ComplexNode(2);
		ComplexNode node3 = new ComplexNode(3);
		ComplexNode node9 = new ComplexNode(9);
		ComplexNode node6 = new ComplexNode(6);
		ComplexNode node5 = new ComplexNode(5);
		ComplexNode node7 = new ComplexNode(7);
		
		node4.next = node1;
		node1.next = node2;
		node2.next = node3;
		node3.next = node9;
		node9.next = node6;
		node6.next = node5;
		node5.next = node7;
		
		node4.sibling = node3;
		node1.sibling = node9;
		node2.sibling = node5;
		node3.sibling = null;
		node9.sibling = node6;
		node6.sibling = null;
		node5.sibling = node2;
		node7.sibling = null;
		
		return node4;
	}
	
	// 输出链表主路线和sibling
	public static void showLink(ComplexNode head) {
		ComplexNode save = head;
		while(head!=null) {
			System.out.printf("%d ", head.val);
			head = head.next;
		}
		System.out.println();
		
		head = save;
		while(head!=null) {
			if(head.sibling!=null) {
				System.out.printf("%d-%d  ",head.val,head.sibling.val);
			}
			head = head.next;
		}
		System.out.println();
	}
}

【数据结构】

public class ComplexNode {
	int val;
	ComplexNode next;
	ComplexNode sibling;
	
	public ComplexNode(int x) {
		val = x;
	}
}

 

你可能感兴趣的:(剑指offer第二版)