1.直接操作
链表反转后的效果如图:
我们将使用三个指针来进行操作,pre是指向新链表的头节点(<1>状态尚未进行操作,旧链表为空),cur是指向待反转链表的头节点,也是当前要反转的节点,next是下一个反转的节点。
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode next = null;
ListNode pre = null;
while(cur!=null){
next = cur.next;//保存下一个待反转节点
cur.next = pre;//为新链表插入节点
pre = cur;//指定为新链表的头节点
cur = next;
}
return pre;
}
2.使用虚拟节点
头插法引用了一个虚拟节点(dummyNode)来进行操作,使得反转过程更好理解。
public ListNode reverseList(ListNode head) {
ListNode dummy = new ListNode(-1,null);
ListNode cur = head;
ListNode next = null;
while(cur!=null){
next = cur.next;//保存下一个待反转节点
cur.next = dummy.next;//反转当前节点
dummy.next = cur;
cur = next;
}
return dummy.next;
}
3.递归法
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head; //出口
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
4.使用栈
把全部元素压栈,每次出栈都指向下一个出栈元素。
public ListNode reverseList(ListNode head) {
Stack<ListNode> s = new Stack();
ListNode temp = new ListNode(-1,null);
ListNode dummy = temp;
while(head!=null){//全部压栈
s.push(head);
head = head.next;
}
while(s.size()>0){
temp.next = s.pop();
temp = temp.next;
}
temp.next = null;//防止成环
return dummy.next;