题目描述
输入一个链表,反转链表后,输出新链表的表头。
思路1:借用外部空间
题目并没有要求原地反转,所以可以采用借外部空间反转,可以将单链表存储为数组,借用数组的索引倒序输出实现反转功能。但这个方法需要额外空间,且需要进行两次遍历,时间和空间复杂度均比较高。
import java.util.ArrayList;
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null){
return null;
}
ArrayList<ListNode> nodeList=new ArrayList<>();
while(head!=null){
nodeList.add(head);
head=head.next;
}
int startIndex=nodeList.size()-1;
for (int i = startIndex; i >=0; i--) {
ListNode node=nodeList.get(i);
if(i==0){
node.next=null;
}
else{
node.next=nodeList.get(i-1);
}
}
//现在头结点是原来的尾节点
head=nodeList.get(startIndex);
return head;
}
}
借用外部空间实现,应该用堆栈也可以。先遍历链表中的每个元素,然后将它们一个个压入堆栈,在新建一个新的链表,把元素逐个从链表中弹出(同时改变指针指向)。
思路2:递归法
逐层确定当前节点有没有next节点,若为空,则表明已经递归到最后一个节点,将该节点的next指向它的父节点,在递归栈中以此类推。
1.先找到最后一个节点,然后从最后一个节点进行反转,当前节点进行反转时,其后面的节点已经完成反转了,不用管。
2.最后返回原来的最后一个节点,即为反转后的头结点。
下面代码中,head.next是5,head是4,而5的next是null,所以递归返回时,head为4,newHead为5.然后根据这个来改变指针指向;
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null||head.next==null){
return head;
}else{
ListNode newhead=ReverseList(head.next);
head.next.next=head;//实现指针反转,将后一个节点的next指向它的前一个节点
head.next=null;//这两句最后的实现效果是null←head←head.next
return newhead;
}
}
}
思路3.迭代法
使用2个指针,把一个链表分成俩个部分, pre是已经反转部分, curr是为反转部分,然后通过俩个指针的配合,不断的右移直到全部反转
1.设置两个指针pre,curr分别指向前一节点和当前节点(第一次迭代,前一节点为null,当前节点为head节点),
2.先将curr的下一节点next记录下来。再让当前节点指向上一节点。(改变头节点的指针指向)
3.将pre和curr分别往后移动,pre指针对应curr,curr指针对应next,然后开始下轮的迭代(逐步去改变每一个节点 的指针指向)
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null){
return null;
}
ListNode preNode=null;
ListNode currNode=head;
while(currNode!=null){
ListNode nextNode=currNode.next;
currNode.next=preNode;//用来改变迭代到的每个元素的指针的指向
preNode=currNode;
currNode=nextNode;
}
return preNode;
}