鏈表逆序


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;
            }
        }    
    }
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM