算法通关村第二关 —— 白银挑战之链表反转拓展问题
本文以介绍与链表反转有关的一些拓展问题,如:
指定区间反转(头插法、穿针引线法)
两两交换链表中的节点
指定区间反转
如图:指定2 - 4节点反转,1、5节点不变
方法一:头插法
先遍历到开始反转的节点,用临时节点保存一下断开的前一个节点cur,断开的后一个节点一个temp(该节点为反转后继续往后连接的节点),然后使用头插法使left到right反转,随后把temp接回虚拟节点处;
/**
* 头插法
*/
public static void headInsert(Node<Integer> head, int left, int right) {
if (head == null) {
return;
}
Node<Integer> dummyNode = new Node<>(-1);
Node<Integer> cur = head;
for (int i = 1; i < left - 1; i++) {
cur = cur.getNext();
}
Node<Integer> pre = cur.getNext();
Node<Integer> temp = pre;
for (int i = 0; i <= right - left ; i++) {
Node<Integer> next = pre.getNext();
pre.setNextNode(dummyNode.getNext());
dummyNode.setNextNode(pre);
pre = next;
}
//尾节点接上
temp.setNextNode(pre);
//断开的节点接上
cur.setNextNode(dummyNode.getNext());
}
方法二:穿针引线法
先记录断开前的pre,第二段断开前的rightNode,以及第二段断开后的下一个节点suc,记录反转的第一个节点为leftNode = pre.next,使用穿针引线法反转,随之pre -> rightNode -> pre.next -> suc,注意,此处第三部没有用leftNode而是用pre.next,是因为在遍历的最后面,leftNode = suc了,而pre的next并没有变,所以可以先连接起后面的,再把前面的连起来
/**
* 穿针引线法
*/
public static void middle(Node<Integer> head, int left, int right) {
Node<Integer> node = head;
for (int i = 1; i < left - 1; i++) {
node = node.getNext();
}
Node<Integer> pre = node;
Node<Integer> leftNode = pre.getNext();
for (int i = 0; i <= right - left; i++) {
node = node.getNext();
}
Node<Integer> rightNode = node;
Node<Integer> suc = rightNode.getNext();
Node<Integer> sub = null;
while (leftNode != suc){
Node<Integer> next = leftNode.getNext();
leftNode.setNextNode(sub);
sub = leftNode;
leftNode = next;
}
pre.getNext().setNextNode(suc);
pre.setNextNode(rightNode);
}
两两交换链表中的节点
实现效果:
利用上虚拟节点,设(1)虚拟节点 temp、(2)当前节点cur、(3)下一个节点next、(4)下一个开始的节点nextStart,取这4各临时变量进行一下交换与赋值
①:cur、next(next指向cur,temp指向next)交换
②:cur指向nextStart
③:temp移到cur处,作为下一个循环的起点
/**
* 两两交换链表中的节点
* */
public static Node<Integer> coupleChange(Node<Integer> head){
if (head == null){
return null;
}
Node<Integer> dummyNode = new Node<>(-1);
dummyNode.setNextNode(head);
Node<Integer> temp = dummyNode;
while (temp.getNext() != null && temp.getNext().getNext() != null ){
Node<Integer> cur = temp.getNext();
Node<Integer> next = cur.getNext();
Node<Integer> nextStart = next.getNext();
temp.setNextNode(next);
next.setNextNode(cur);
cur.setNextNode(nextStart);
temp = cur;
}
return dummyNode.getNext();
}