剑指Offer 24 25

86 阅读1分钟

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

剑指 Offer 24. 反转链表

题目

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

限制:

0 <= 节点个数 <= 5000

方法一

朴素方法:使用前后两个指针,将后一个的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) {
        if(head == null) return head;
        
        ListNode dummy = new ListNode();
        dummy.next = head;
        
        ListNode a = dummy, b = head;
        while (b != null) {
            ListNode c = b.next;
            b.next = a;
            a = b;
            b = c;
        }
        dummy.next.next = null;
        return a;
    }
}

时间复杂度: O(n)

空间复杂度: O(1)

注意: 最后需要将头结点的next指针置空

剑指 Offer 25. 合并两个排序的链表

题目

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

示例1:

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

限制:

0 <= 链表长度 <= 1000

方法一

双指针:首先创建一个虚拟头结点;接着通过比较两个指针指向结点的值,头结点的next指向值小的结点,并且该结点向后一步;直到某一个链表全部遍历完为止;

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
​
        ListNode dummy = new ListNode(), p = dummy;
        
        while(l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                p = p.next = l1;
                l1 = l1.next;
            }else {
                p = p.next = l2;
                l2 = l2.next;
            }
        }
        if (l1 != null) p.next = l1;
        if (l2 != null) p.next = l2;
        return dummy.next;
    }
}

时间复杂度: O(n)

空间复杂度: O(1)

注意: 当循环体结束时,可能存在还有一个链表没遍历完,所以需要特判一下。