描述
反转链表
思路1:使用栈存储
使用栈存储每个节点,再pop取出节点,构造新链表。(也可以用列表,倒序取出,i--)
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head == null) {
return null;
}
Stack<ListNode> stack = new Stack<>();
ListNode p = head;
while(p != null) {
stack.push(p);
p = p.next;
}
ListNode ret = stack.pop();
p = ret;
while(!stack.isEmpty()) {
p.next = stack.pop();
p = p.next;
}
//最后一个节点是原链表的头节点,next是第二个节点,需要断开,否则会构成环
p.next = null;
return ret;
}
}
思路2:三指针
三指针:前一个节点、当前节点、下一个节点
public class Solution {
public ListNode ReverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
ListNode tmp;
while(cur != null) {
//保存下一个节点
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
思路3:递归
递归回弹时(出栈时)处理
public class Solution {
public ListNode ReverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode node = ReverseList(head.next);
head.next.next = head; //尾节点指向倒数第二个节点
head.next = null; //指向null
return node;
}
}
思路4:递归
递归:f(n,n-1)=f(n+1,n)+n指向n-1
[1,null], [2,1], [3,2], [null,3](终止), [3,2], [2,1], [1,null]
public class Solution {
public ListNode ReverseList(ListNode head) {
return recur(head, null);
}
private ListNode recur(ListNode cur, ListNode pre) {
if (cur == null) {
return pre;
}
// 递归后继节点
ListNode res = recur(cur.next, cur);
// 修改节点引用指向
cur.next = pre;
// 返回反转链表的头节点
return res;
}
}
思路5:尾递归
类似于三指针
public class Solution {
public ListNode ReverseList(ListNode head) {
return recur(head, null);
}
private ListNode recur(ListNode cur, ListNode newHead) {
if (cur == null) {
return newHead;
}
//保存下一个节点
ListNode next = cur.next;
//断开原链表,指向新链表
cur.next = newHead;
return recur(next, cur);
}
}
思路5:倒着构造链表
倒着构造链表,保存已构造好的链表,每次循环创建新的头节点,连接上已构造好的链表
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head == null) {
return null;
}
ListNode ret = new ListNode(head.val);
while(head.next != null) {
ListNode newHead = new ListNode(head.next.val);
newHead.next = ret;
ret = newHead;
head = head.next;
}
return ret;
}
}