剑指Offer 24-25

111 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

24、反转链表

题目:要求定义一个函数将输入的链表进行反转,之后输出链表的头节点。

解题思路

复习题,反转链表有非递归和递归,非递归的思路就是链表的头插法,代码如下:

public ListNode reverseList(ListNode head) {
    ListNode headPoint = new ListNode(-1);
    while(head!=null){
        ListNode temp = head.next;
        head.next = headPoint.next;
        headPoint.next = head;
        head = temp;
    }
    return headPoint.next;
}

递归方法较为巧妙,首先到达末尾节点,之后需要注意的是不能通过接收末尾节点来进行链表的反转,需要根据源节点进行反转,代码如下:

public ListNode reverseList(ListNode head) {
    if(head==null||head.next==null) return head;
    ListNode res = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return res;
}

25、合并两个有序链表

题目:给定两个有序的递增链表,要求对这两个递增链表进行合并,使得合并后的链表仍然保持有序,并且输出合并后的链表头节点。

例如:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

解题思路

合并链表依然可以使用递归和非递归的方法,非递归的方法是使用另一个链表,首先遍历两个链表,每次判断两个链表的大小,之后依次插入新链表之后即可,最后可通过判断两个链表哪个为空返回最终的结果,代码如下:

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    if(l1==null) return l2;
    if(l2==null) return l1;
    ListNode temp = new ListNode(-1);
    ListNode res = temp;
    while(l1!=null&&l2!=null){
        if(l1.val<=l2.val){
            res.next = l1;
            l1 = l1.next;
        }else {
            res.next = l2;
            l2 = l2.next;
        }
        res = res.next;
    }
    res.next = l1==null?l2:l1;
    return temp.next;
}

递归的方法很简单,直接判断两个链表,之后根据链表的结果直接递归即可,此方法直接在原链表的基础上进行修改,代码如下:

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    if(l1 == null) return l2;
    if(l2 == null) return l1;
    if(l1.val<=l2.val){
        l1.next = mergeTwoLists(l1.next, l2);
        return l1;
    }else {
        l2.next = mergeTwoLists(l1, l2.next);
        return l2;
    }
}