0
点赞
收藏
分享

微信扫一扫

链表的相关操作

霸姨 2022-03-14 阅读 81

一个链表的数据结构如下

public class ListNode {
	public int val;
	public ListNode next=null;
	public ListNode rand=null;
	ListNode(int val){  //构造方法 :构造方法和类名相同   
        this.val=val;     //把接收的参数赋值给当前类的val变量
    }
}

问题:如果一个链表的next节点指向它的下一个节点,它的rand节点指向随机节点(可以为null),那么我们应该怎么复制这个链表。
首先我们应该知道如果普通的for循环直接每次创建一个节点来赋值创建肯定是不行的,因为rand节点是指向随机节点的一个值。那么第一个解法:
先循环用hashMap保存每一个创建的节点信息,然后再循环修改值。(时间复杂度为O(n) 空间复杂度为O(n))。
代码如下:

public static ListNode copyListWithRand(ListNode head){
		ListNode node=head;
		HashMap<ListNode,ListNode> hashMap=new HashMap<>();
		while(node!=null){//先复制节点 存入map中
			hashMap.put(node,new ListNode(node.val));
			node=node.next;
		}
		node=head;
		while(node!=null){//再次遍历进行节点的赋值
			ListNode temp=hashMap.get(node);
			temp.next=node.next;
			temp.rand=node.rand;
			node=node.next;
		}
		return hashMap.get(head);//返回头节点
	}

但是如果我们想要时间复杂度为O(n),空间复杂度O(1)的情况下完成这个算法应该怎么办,循环的时候创建节点直接放到我们被复制节点的后面,如图:
在这里插入图片描述
复制完过后我们再次遍历进行操作,首先将1节点的next指针指向2,然后将被赋值节点 1’ 的next指针指向2’就是 1.next.next,然后将 1’的rand指针指向 1的rand的next节点。直接看代码:

public static ListNode copyListWithRandBetter(ListNode head){
		ListNode node=head;
		while(node!=null){//先创建节点
			ListNode nodeTemp=new ListNode(node.val);
			nodeTemp.next=node.next;
			node.next=nodeTemp;
			node=nodeTemp.next;
		}
		node=head;
		ListNode result=node.next;//保存要返回节点的头节点
		while(node!=null){
			ListNode nodeTemp=node;
			ListNode nodeTemp2=node.next;
			nodeTemp.next=nodeTemp2.next;//将node节点指针复原  然后给复制节点进行赋值操作
			nodeTemp2.next=nodeTemp.next==null?null:nodeTemp.next.next;//node的next节点可能指向空
			nodeTemp2.rand=nodeTemp.rand==null?null:nodeTemp.rand.next;//node的rand节点可能指向空
			node=node.next;
		}
		return result;//返回头节点
	}
举报

相关推荐

0 条评论