/*class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 * 
 * @param pHead1 ListNode类 
 * @param pHead2 ListNode类 
 * @return ListNode类
 */

/**
 * 解法一:迭代
 * 思路:
 * (1)新建一个空的表头后面连接两个链表排序后的结点。
 * (2)遍历两个链表都不为空的情况,取较小值添加在新的链表后面,每次只把被添加的链表的指针后移。
 * (3)遍历到最后肯定有一个链表还有剩余的结点,它们的值将大于前面所有的,直接连在新的链表后面即可。
 * 时间复杂度: O(n),最坏情况遍历2 * n个结点
 * 空间复杂度: 0(1),无额外空间使用,新建的链表属于返回必要空间
 */
export function Merge(pHead1: ListNode, pHead2: ListNode): ListNode {
    if (pHead1 == null) return pHead2
    if (pHead2 == null) return pHead1

    let head: ListNode = new ListNode()// 加一个表头
    let cur: ListNode = head

    while (pHead1 != null && pHead2 != null) { 
        if (pHead1.val <= pHead2.val) { // 取较小值的节点
            cur.next = pHead1
            pHead1 = pHead1.next // 移动取值的指针
        } else {
            cur.next = pHead2
            pHead2 = pHead2.next
        }
        cur = cur.next // 指针后移
    }
     
    if (pHead1 != null) cur.next = pHead1
    if (pHead2 != null) cur.next = pHead2

    return head.next // 返回值去掉表头
}

/**
 * 解法二:递归
 * 思路:
 * (1)每次比较两个链表当前结点的值,然后取较小值的链表指针往后,另一个不变送入递归中。
 * (2)递归回来的结果我们要加在当前较小值的结点后面,相当于不断在较小值后面添加结点。
 * (3)递归的终止是两个链表为空。
 * 时间复杂度: O(n),最坏相当于遍历两个链表每个结点一次
 * 空间复杂度: O(n), 递归栈长度最大为 n
 */
export function Merge(pHead1: ListNode, pHead2: ListNode): ListNode {
    if (pHead1 == null) return pHead2
    if (pHead2 == null) return pHead1

    if (pHead1.val <= pHead2.val) { // 先用较小的值的节点
        pHead1.next = Merge(pHead1.next, pHead2)
        return pHead1
    } else {
        pHead2.next = Merge(pHead1, pHead2.next)
        return pHead2
    }
}

一站式解决前端面试高频算法题

https://github.com/hovinghuang/fe-agorithm-interview