剑指Offer:反转链表
由于链表具有天然的递归结构,反转链表其实很容易想到递归的方式。这里暂不说了。说一下非递归的方式
非递归的方式
由于链表的next维持关系链的关键。反转的过程就需要用额外的指针指向当前节点的前一节点和后一节点,不然的话就会发生断链了。
图示:
具体步骤伪代码可为:
1. pNext指向当前节点的next以保持链 pNext = current.next;
2.当前节点的nextf指向前一节点(开始反转)current.next = prev
3. prev 指针指向当前指针(即往后)prev = current
4. 当前的指针也往后 current = pNext;
步骤繁琐点帮助理解,其实当前节点的指针其实就是head节点了。
代码:
public class Solution { public ListNode reverseList(ListNode head) { //空判断 if(head == null) return head; //3个节点分别指向前一节点,当前节点,下一节点。 ListNode prev = null; ListNode current = head; ListNode pNext; //结束条件就是current节点成为了null时,那么prev节点就成为反转后的头节点了。 while(current!=null){ pNext = current.next; current.next = prev; prev = current; current = pNext; } return prev; } }
递归的方式
//递归的方式要注意递归到底的情况以及和子递归结果的组合。
1.递归到底情况:当链表为null或者链表只有一个节点,则直接返回链表头结点
2.注意宏观语义:函数的返回结果是已经反转完成链表。所以考虑现有头结点与子递归函数的结果的组合。
那就是head.next已经是子递归函数的最后一个元素了。直接将头结点接在后面就好了。
head.next.next = head;
head.next = null;
public class Solution { public ListNode reverseList(ListNode head) { if(head==null||head.next ==null) return head; ListNode res= reverseList(head.next); head.next.next = head; head.next = null; return res; } }
gitHub源码:反转链表
图片来源:https://www.cnblogs.com/csbdong/p/5674990.html