算法通关村第二关 —— 青铜挑战之链表反转
本文就三种方法实现链表的反转
一:虚拟节点
二:辅助节点
三:递归
实现效果
1 -> 2 -> 3 -> 4 -> 5
5 -> 4 -> 3 -> 2 -> 1
测试代码
public static void main(String[] args) {
Node<Integer> five = new Node<>(5);
Node<Integer> four = new Node<>(4);
Node<Integer> three = new Node<>(3);
Node<Integer> two = new Node<>(2);
Node<Integer> one = new Node<>(1);
Link<Integer> link = Struct.getLink(new Node[]{one, two, three, four, five});
print(link.getHead());
// dummyNode(link);
// supNode(link);
// recursion(link.getHead(),link);
// print(link.getHead());
Node<Integer> reverse = reverse(link.getHead());
print(reverse);
}
public static void print(Node<Integer> head) {
while (head != null) {
System.out.print(head.getVal() + " ");
head = head.getNext();
}
System.out.println();
}
public static Link<Integer> getLink(Node<Integer>[] nodes) {
Link<Integer> link = new Link<>();
Arrays.asList(nodes).forEach(link::append);
return link;
}
一、虚拟节点
定义虚拟节点,然后依次从链表中取出节点,拼接在虚拟节点后,最后可得虚拟节点的next为反转后链表的head
送上代码
/**
* 通过虚拟节点,实现链表反转
*/
public static void dummyNode(Link<Integer> link) {
Node<Integer> dummyNode = new Node<>(-1);
Node<Integer> cur = link.getHead();
while (cur != null) {
//临时保存next
Node<Integer> next = cur.getNext();
//cur的next赋值
cur.setNextNode(dummyNode.getNext());
//dummyNode的next赋值
dummyNode.setNextNode(cur);
//下移
cur = next;
}
print(dummyNode.getNext());
}
二、辅助节点 + 指针
遍历链表,初始化指针指向新链表的表头,然后逐个加到新链表中作为新的head,遍历完成后指针指向新的head
送上代码
/**
* 通过辅助节点,实现链表反转
*/
public static void supNode(Link<Integer> link) {
Node<Integer> prev = null;
Node<Integer> cur = link.getHead();
while (cur != null) {
Node<Integer> next = cur.getNext();
cur.setNextNode(prev);
prev = cur;
cur = next;
}
assert prev != null;
print(prev);
}
三、递归
单项链表反转之所以吃力,就是因为方向只有从头节点往后,若先操作前面的节点,中间就会断开,除非像用集合的方式,将整个链表的节点都记录下来,然后各节点的next就很方便操作了
递归也类似,类似于使用栈把所有的节点存起来,然后通过弹栈从后面更换方向
送上代码
/**
* 通过递归,实现链表反转
*/
public static Node<Integer> recursion(Node<Integer> head){
if (head == null || head.getNext() == null){
return head;
}
Node<Integer> reverse = reverse(head.getNext());
head.getNext().setNextNode(head);
head.setNextNode(null);
return reverse;
}