青铜挑战:手写链表反转
方法一:利用额外空间——栈来实现链表反转
数据结构中栈的特点就是先进后出,只要把给定链表的每个节点压栈,然后再一个一个出栈连成新链表就可以了。
代码如下:
public static ListNode reverseListMethod2(ListNode head) {
if (head == null) {
return head;
}
Stack<ListNode> stack = new Stack<>();
// 先遍历一遍链表,将各个 head 压栈
while (head != null) {
stack.push(head);
head = head.next;
}
// 此时栈中栈顶元素即是原链表的尾节点,将它赋值给res返回链表,作为返回链表的头节点
ListNode res = stack.pop();
// 申请一个中间节点,让temp移动,而不是让res链表头节点移动;
// 如果不申请中间节点,使用res来记录栈中弹出的各节点,那么最终res就会变成栈中最后一个弹出的节点,而不是一条链
ListNode temp = res;
while (!stack.isEmpty()) {
ListNode cur = stack.pop();
// 让 栈中弹出的节点的指针指向 null,保证 cur 是单个节点,而不是链
cur.next=null;
temp.next=cur;
temp = temp.next;
}
return res;
}
注意:一定要让 cur.next=null;即让每个弹出的链表节点指向null; 因为栈中记录的并不是单个节点,也可能是链;
方法二:不使用额外空间变量来反转链表
此时就需要改变原链表中各个节点指针的指向;
完整代码如下:
// 假设题目输入链表结构为 1-->2-->3-->4-->5
public static ListNode reverseListNode(ListNode head){
ListNode res=null; // 作为返回节点
ListNode next=null; // 记录head原来指针的指向;
while(head != null){
// 单个节点改变指针指向的过程
next=head.next;
head.next=res;
res=head;
head=next;
}
return res;
}
建议将整个过程在纸上画一遍,这样才能容易的理解各个节点指针变化的过程;
结果如下: