鏈表逆序

Leedcode 206 鏈表逆序I

從頭逆序java

圖解步驟this

備份head.next(原下一節點),修改head.next指向新頭,移動修改兩鏈表的頭指針(新指向新的節點(原頭節點),原再指向下一節點[備份點])spa

  • 迭代法
/**
 * 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

部分逆序指針

圖解步驟code

  • 迭代法blog

    /**
     * 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;
            }
        }    
    }
相關文章
相關標籤/搜索