反转一个单链表。(来源力扣)
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
思路分析:
反转链表的关键在于定义一个保存当前节点的下一个节点的节点,通过使用该节点去实现当前节点的后移。
方法一:
//定义一个新的链表,实现链表的反转
public ListNode2 reverseList1(ListNode2 head) {
if(head==null||head.next==null){
return head;//链表只有一个节点或空的话,直接返回
}
ListNode2 reverseNode=new ListNode2();//定义一个新的节点
ListNode2 saveNode=null;//用来保存当前节点的下一个节点
ListNode2 temp=head;
while(temp!=null){
saveNode=temp.next;
temp.next=reverseNode.next;
reverseNode.next=temp;
temp=saveNode;//将当前节点后移
}
return reverseNode.next;
}
方法二:因为定义新链表实现链表的反转其实是对空间的一种浪费,所以只需要改变链表的next的指向(需要多定义一个指针去调整位置),就可以满足题目要求。
//借助pre==null,通过改变next的指向实现链表的反转(双指针的应用)
public ListNode2 reverseList2(ListNode2 head) {
ListNode2 temp=head;
ListNode2 curNode=null;
ListNode2 pre=null;//通过pre和curNode去移动当前节点的位置和next指向的位置。
while(temp!=null){
curNode=temp.next;//保存下一个节点
temp.next=pre;
//调整pre和temp的位置
pre=temp;
temp=curNode;
}
return pre;
}
方法三:采用递归,和方法二做法相同
public ListNode2 reverseList3(ListNode2 head) {
return reverse(null,head);
}
public ListNode2 reverse(ListNode2 pre,ListNode2 cur){
if(cur==null){//无节点直接返回
return pre;
}
//以下操作和双指针法一样
ListNode2 tempNode=cur.next; //保存当前节点的下一个节点
cur.next=pre;
//移动pre和当前节点的位置
pre=cur;
cur=tempNode;
return reverse(pre,cur);
}