《剑指Offer》Java刷题 NO.15 反转链表

《剑指Offer》Java刷题 NO.15 反转链表(链表、多指针、递归)

传送门:《剑指Offer刷题总目录》

时间:2020-02-24
题目:
输入一个链表,反转链表后,输出新链表的表头。


思路:
1.非递归方法:

  • 除了传进来的头节点作为当前结点之外,需要两个空结点,pre和next
  • pre记录当前指针的前一个指针,反转之后应该是当前节点指向pre
  • next结点用来作为临时结点存储当前结点的下一个,这样当前结点反向以后才不会断掉找不到后面的结点
    循环,知道当前节点的下一个是null时,当前结点就是反转后的列表的头结点
    2.递归方法:(我想不出来啊…哭了…递归太难了)
  • 递归终结条件:当前结点.next=null,那么当前结点(原链表的尾节点)就是反转后链表的头结点,直接返回当前结点
  • 递归语句:ListNode newHead=reverseList(head.next)(递归处理除头结点之外后面的链表);
  • 返回语句:return newHead;
    这样就能保证一步一步调用之后的返回值始终是原链表的尾节点,也就是反转后新链表的头结点
  • 每次递归时先用temp结点把当前结点.next保存下来, 每次循环时把当前结点的下一个(temp)指向当前结点,然后当前结点下一个指向null

扩展:
每隔k个元素进行一次反转
Java代码:

/**
 * 输入一个链表,反转链表后,输出新链表的表头。
 */
public class ReverseList {
    /**
     *非递归方法
     */
    public static ListNode reverseList1(ListNode head){
        if(head==null) return null;//先判断链表是否为空
        ListNode pre=null;
        ListNode next=null;//分别记录当前结点的前一个和后一个
        while(head!=null){//当前结点为空时说明当前结点的pre已经是尾节点了,返回pre
            next=head.next;//先把下一个节点保存下来,不然断链之后会找不到下一个
            head.next=pre;//当前结点的下一个指向pre(前一个结点)
            pre=head;
            head=next;//当前结点和pre都后移一个
            //最后的head(null)是和前面已经反转好的链表没连接起来的,所以需要返回pre
        }
        return pre;
    }
    /**
     * 递归方法
     */
    public static ListNode reverseList2(ListNode head){
        if(head==null||head.next==null) return head;
        //head==null主要是为了判断初始链表是否为空,head.next==null是为了满足递归终止条件
        ListNode temp=head.next;
        ListNode newHead=reverseList2(temp);
        temp.next=head;
        head.next=null;
        return newHead;
        //假设一共0~n-1个结点
        //最后:head=n-2,temp=n-1,返回newHead=n-1,null<--(n-2)<--(n-1)
        //弹出上一个状态的值,head=n-3,temp=n-2,null<--(n-3)<--(n-2)<--(n-1)。。继续
    }
}
class ListNode{
    int val;
    ListNode next=null;
    ListNode(int val){
        this.val=val;
    }
    public void setNext(ListNode node){
        this.next=node;
    }
    public static void print(ListNode head){
        while(head!=null){
            System.out.println(head.val);
            head=head.next;
        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值