反轉鏈表
給你單鏈表的頭節點 head ,請你反轉鏈表,並返回反轉后的鏈表。
示例 1:
輸入:head = [1,2,3,4,5]
輸出:[5,4,3,2,1]
作者:力扣 (LeetCode)
鏈接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnnhm6/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
方法1.逆置優先想到棧
1.遍歷鏈表,元素入棧
2.設置一個始終指向隊尾的變量,依次將元素退棧,鏈尾元素連接新出棧元素,鏈尾后移
3.最后一個元素next置空
4.返回第一個出棧的元素
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
Stack<ListNode> stack = new Stack<>();
ListNode p = head;
while(p != null){
stack.push(p);
p = p.next;
}
p = stack.pop();
head = p;
while(!stack.empty()){
p.next = stack.pop();
p = p.next;
}
p.next = null;
return head;
}
方法2.直接逆置
1.設置一個新鏈頭,始終指向新鏈頭元素,head始終指向舊鏈頭
2.按照逆置關系,舊鏈頭應該指向新鏈頭,但是直接舊.next = 新 會丟失當前舊.next,所以設置一個臨時變量暫存舊.next,然后在進行連接
3.連接后,保持兩個鏈頭元素的位置
4.返回新鏈頭
public ListNode reverseList(ListNode head) {
ListNode newHead = null;
while(head != null){
ListNode temp = head.next;
head.next = newHead;
newHead = head;
head = temp;
}
return newHead;
}
方法3.遞歸
逆置可以把大問題分解成解決過程一樣的子問題然后在反過來解決大問題嗎?
考慮傳入的元素是頭結點,方法目的是把頭結點對應的鏈表逆置返回頭節點,那么如果傳入頭結點的next,將他對應的鏈表逆置返回其頭結點,解決的問題是一樣的->當前問題和子問題解決方法一致。
這時只需要把當前節點連接到新鏈表的尾部,也就是原頭結點的next.next就解決了當前問題->解決子問題后可以解決當前問題。
所以,可以使用遞歸。
1.遞歸出口為當前元素的next為空(既然為空那就算不上一個子問題)
2.遞歸head.next返回新鏈表
3.將head連接到新鏈鏈尾 head.next.next = head
4.head成為新鏈尾,故next置空
5.返回本輪問題的解->逆置后的鏈頭
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode headNext = head.next;
ListNode newHead = reverseList(headNext);
headNext.next = head; //(head.next.next = head)
head.next = null;
return newHead;
}