方法一:递归反转法
首先要确定递归的终止条件
是当前节点为空(这里是为了处理空链表的情况)或者当前节点的下一个节点为空
即:head == null || head.next == null
对于递归函数内部而言,其每次返回的cur其实都是最后一个节点,同时在内部还完成了当前节点与下一个的节点的反向,下面以图示的5节点链表为例来展示详细的执行过程
public ListNode reverseListNode(ListNode head) {
if(head==null || head.next==null) {
return head;
}
ListNode cur = reverseListNode(head.next);
head.next.next = head;
head.next = null;
return cur;
}
-
时间复杂度:O(n) 空间复杂度:O(n)
方法二:双(三)指针法(迭代法)
双(三)指针法是迭代法中的一种,它的主要思想是分别定义两(三)个指针,一个指针pre最初是指向 null 的,另一个指针 cur 指向 head,然后不断遍历 cur。每次迭代到 cur,都将 cur 的 next 指向 pre,然后 pre 和 cur 前进一位。当cur为空时,结束迭代,此时pre就是最后一个节点,返回即可。(此处三指针就是加上一个next指针指向cur的下一个节点,三指针和双指针的方法类似,两种方法精髓是相同的,所以放在一起写了)下面以节点1和节点2的双指针反转过程为例来展示详细的执行过程
public ListNode reverseListNode(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
时间复杂度:O(n) 空间复杂度:O(1)
方法三:头插法(迭代法)
头插法的主要思想是重新建一个新头节点,然后对原链表进行遍历,在遍历过程中把每个节点当作头节点插入到新建链表中。最后,新建的链表就是反转后的链表,注意返回时要返回新建节点的下一个节点。
下面以节点1和节点2的反转过程为例来展示详细的执行过程
public ListNode reverseListNode(ListNode head) {
ListNode dump = new ListNode(-1);
ListNode cur = head;
while(cur != null){
ListNode next = cur.next;
cur.next = dump.next;
dump.next = cur;
cur = next;
}
return dump.next;
}
时间复杂度:O(n) 空间复杂度:O(1)
方法四:就地逆置反转法(迭代法)
就地逆置反转法和头插法的实现思想相似,它们的区别在于头插法是通过建立一个新链表实现的,而就地逆置法则是直接对原链表做修改,从而实现将原链表反转。在就地逆置反转法中需要借助两个指针实现,下面以节点2和节点3的反转过程为例来展示详细的执行过程
public ListNode reverseListNode(ListNode head) {
if(head == null)
return head;
ListNode dump = new ListNode(-1);
dump.next = head;
ListNode pre = dump.next;
ListNode cur = pre.next;
while(cur != null){
pre.next = cur.next;
cur.next = dump.next;
dump.next = cur;
cur = pre.next;
}
return dump.next;
}
时间复杂度:O(n) 空间复杂度:O(1)
方法五:栈实现反转
除了上述的几种方式外,还可以利用栈的先进后出的思想来实现单链表的反转,首先对链表进行遍历并将各个节点入栈,当节点出栈的时候就是逆序的了。(需要注意在出栈的时候要消除每个节点的next指向。)
public ListNode reverseListNode(ListNode head) {
if(head == null)
return head;
Stack<ListNode> stack = new Stack();
ListNode temp = head;
while(temp != null){
stack.push(temp);
temp = temp.next;
}
ListNode dump = stack.pop();
ListNode cur = dump;
while(!stack.isEmpty()){
ListNode node = stack.pop();
node.next = null;
cur.next = node;
cur = node;
}
return dump;
}
时间复杂度:O(n) 空间复杂度:O(n)