1.复制特殊链表(每个节点包括next和random两个指针)
(1)空间复杂度为O(N)的方法
public Node CopyListWithRandom(Node head) {
if (head == null) return null
HashMap<Node, Node> map = new HashMap<>()
Node next = null
Node cur = head
while (cur != null) {
next = cur.next
map.put(cur, new Node(cur.val))
cur = next
}
cur = head
while (cur != null) {
next = cur.next
map.get(cur).next = cur.next
map.get(cur).random = cur.random != null ? cur.random : null
cur = next
}
return map.get(head)
}
(2)空间复杂度为O(1)的方法
public Node CopyListWithRandom1(Node head) {
if (head == null) return null
Node cur = head
Node next = null
Node rehead = null
while (cur != null) {
next = cur.next
rehead = new Node(cur.val)
rehead.next = next
cur.next = rehead
cur = next
}
cur = head
while (cur!=null){
next = cur.next.next
rehead = cur.next
rehead.random = cur.random!=null?cur.random.next:null
cur = next
}
cur = head
rehead = head.next
Node help = null
while (cur!=null){
next = cur.next.next
help = cur.next
cur.next = next
help.next = next!=null?next.next:null
cur = next
}
return rehead
}
2.寻找两个链表的交点(可能有环)
public Node FindFirstInsertNode(Node head1,Node head2){
if(isLoop2(head1)==null && isLoop2(head2)==null) return FindFirstInsertNode1(head1,head2)
if(isLoop2(head1)==null&&isLoop2(head2)!=null || isLoop2(head1)!=null && isLoop2(head2)==null) return null
return FindFirstInsertNode2(head1,head2)
}
//判断当前链表是否有环,如果有环返回第一个入环节点,如果没有返回null
public Node isLoop1(Node head){ // 哈希表法,空间复杂度O(N)
if (head==null||head.next==null) return null
HashSet<Node> hashSet = new HashSet<>()
Node cur = head
while (cur!=null){
if(hashSet.contains(cur)){
return cur
}else {
hashSet.add(cur)
}
cur = cur.next
}
return null
}
public Node isLoop2(Node head){ //双指针法,空间复杂度O(1)
if(head == null||head.next==null) return null
Node fast = head.next.next
Node slow = head.next
while (fast!=slow){
if (fast==null || slow==null || fast.next==null){
return null
}
fast = fast.next.next
slow = slow.next
}
fast = head
while (fast!=slow){
fast = fast.next
slow = slow.next
}
return fast
}
public Node FindFirstInsertNode1(Node head1,Node head2){ // 如果两个都是无环的,调用这个方法
if(head1==null || head2==null) return null
Node cur1 = head1
Node cur2 = head2
int len1 = 0
int len2 = 0
while (cur1.next!=null){
cur1 = cur1.next
len1++
}
while (cur2.next!=null){
cur2 = cur2.next
len2++
}
if(cur1!=cur2) return null
cur1 = len1>len2?head1:head2
cur2 = len1>len2?head2:head1
int len = Math.abs(len1-len2)
while (len>0){ // cur1先走
cur1 = cur1.next
len--
}
while (cur1!=cur2){
cur1 = cur1.next
cur2 = cur2.next
}
return cur1
}
public Node FindFirstInsertNode2(Node head1,Node head2){ // 如果两个都有环
Node n1 = isLoop2(head1)
Node n2 = isLoop2(head2)
Node cur1 = head1
//如果相交节点在环外,两个链表入环节点一定相同,简化为方法1
if(n1==n2){
int len1 = 0
int len2 = 0
Node cur2 = head2
while (cur1!=n1){
cur1 = cur1.next
len1++
}
while (cur2!=n2){
cur2 = cur2.next
len2++
}
cur1 = len1>len2?head1:head2
cur2 = len1>len2?head2:head1
int len = Math.abs(len1-len2)
while (len>0){
cur1 = cur1.next
len--
}
while (cur1!=cur2){
cur1 = cur1.next
cur2 = cur2.next
}
return cur1
}else { //入环节点不相同:1.有交点 2.没有交点
cur1 = n1
while (cur1!=n2){
cur1 = cur1.next
if(cur1==n1) return null
}
return n2
}
}