链表逆序

Posted 妙啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表逆序相关的知识,希望对你有一定的参考价值。

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

以上是关于链表逆序的主要内容,如果未能解决你的问题,请参考以下文章

算法与数据结构单链表的增删改查逆序打印与输出合并有序链表

设计鲁棒性的方法:输入一个链表的头结点,逆序遍历打印该链表出来

给定两个逆序非空链表,求链表中两数相加的和,且仍返回逆序链表

1.1链表逆序

算法--链表的K逆序问题

链表逆序