Leedcode 206 鏈表逆序I
從頭逆序
圖解步驟
備份head.next(原下一節點),修改head.next指向新頭,移動修改兩鏈表的頭指針(新指向新的節點(原頭節點),原再指向下一節點[備份點])
- 迭代法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode curr=head;
ListNode newHead=null;
while(curr!=null){
//備份next
ListNode bak=curr.next;
//修改next指向,既將head與newHead連接
curr.next=newHead;
//移動head和newHead
newHead=curr;
curr=bak;
}
return newHead;
}
}
- 遞歸法
public ListNode reverseList(ListNode head) {
//遞歸到最下一層獲得末尾節點
if (head == null || head.next == null) return head;
//每次遞歸完成后head都會往前移位
ListNode p = reverseList(head.next);
//head.next既當前節點(5),將其下一節點指向前一節點(4)
head.next.next = head;
//將前一節點(4)指向null
head.next = null;
//返回固定節點(5)
return p;
}
LeedCode 92 鏈表逆序II
部分逆序
圖解步驟
-
迭代法
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode reverseBetween(ListNode head, int m, int n) { //需要逆置的節點數 int len=n-m+1; //備份原始頭節點 ListNode result=head; ListNode pre_head=null; //找到開始逆置節點 for(int k=1;k<m;k++){ //找到逆置節點前節點 pre_head=head; head=head.next; } //設置new_head ListNode new_head=head; //備份更改后的尾節點 ListNode modify_tail=head; //逆置begin for(int num=0;num<len;num++){ //備份head的下節點 ListNode bak_next=head.next; //下節點指向新頭 head.next=new_head; //新頭向前移 new_head=head; //原頭后移 head=bak_next; } //將后置節點連上 modify_tail.next=head; //將前驅節點連上 if(pre_head!=null) pre_head.next=new_head; else result=new_head; //若從頭節點逆置,返回值應該為新頭節點 //返回原始頭 return result; } }
-
遞歸換值法
class Solution { private boolean stop; private ListNode left; public ListNode reverseBetween(ListNode head,int m,int n){ this.left=head; this.stop=false; this.recurseAndReverse(head,m,n); //最上層的還是head節點,直接返回head return head; } /** *function:遞歸到最下層並進行一次交換 *tips:每次的最右節點都是回溯的 */ public void recurseAndReverse(ListNode right,int m,int n){ //如果右到底,結束遞歸 if(n==1) return; //為了找到右節點 right=right.next; //為了找到左節點 if(m>1){ this.left=this.left.next; } //遞歸獲得最左及最右節點 recurseAndReverse(right,m-1,n-1); //遞歸后的每一次都從這里開始交換 //定義暫停條件 if(this.left==right||this.left==right.next){ this.stop=true; } if(!this.stop){ //交換值 int temp=this.left.val; this.left.val=right.val; right.val=temp; //左就向右移動一位 //右通過回溯左移一位 this.left=this.left.next; } } }