Skip to content

Latest commit

 

History

History
145 lines (132 loc) · 3.62 KB

LinkedList.md

File metadata and controls

145 lines (132 loc) · 3.62 KB
/**
 * 1. 递归
 * T(n): O(n)
 * S(n): O(n)
 */
export function printListFromTailToHead(head: ListNode): number[] {
    if(head === null) {
        return []
    }
    const res = printListFromTailToHead(head.next)
    res.push(head.val)
    return res 
}
/**
 * 2. 头插法
 * 由于本题要求以数组格式返回,所以构建逆序链表后还要遍历一遍,时间复杂度是O(n²), 不推荐
 * T(n): O(n²)
 * S(n): O(n)
 */

public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
    // 头插法构建逆序链表
    ListNode head = new ListNode(-1);
    while (listNode != null) {
        ListNode memo = listNode.next;
        listNode.next = head.next;
        head.next = listNode;
        listNode = memo;
    }
    // 构建 ArrayList
    ArrayList<Integer> ret = new ArrayList<>();
    head = head.next;
    while (head != null) {
        ret.add(head.val);
        head = head.next;
    }
    return ret;
}
/**
 * 3. 栈
 * 使用js数组内置api可以轻松模拟栈后进先出的行为(也可以自己实现一个栈)
 * T(n): O(n)
 * S(n): O(n)
 */
export function printListFromTailToHead(head: ListNode): number[] {
    const res = [];
    while (head) {
        res.unshift(head.val);
        head = head.next;
    }
    return res;
}

/**
 * 4. 尾插法+反转数组
 * T(n): O(n)
 * S(n): O(n)
 */
function reversePrintOptimized(head: ListNode | null): number[] {
    const res: number[] = [];
    while (head !== null) {
        res.push(head.val); // 尾插法:O(1)
        head = head.next;
    }
    return res.reverse(); // 反转数组:O(n)
}
/**
 * 1. 头插法(迭代)
 * T(n): O(n)
 * S(n): O(1)
 */
function reverseList(head: ListNode | null): ListNode | null {
    let prev = null
    let cur = head

    while(cur !== null) {
        const next = cur.next
        cur.next = prev
        prev = cur
        cur= next
    }
    return prev
};
/**
 * 2. 递归
 * T(n): O(n)
 * S(n): O(n)
 */
function reverseList(head: ListNode | null): ListNode | null {
    // 递归终止条件:空链表或单节点
    if (head === null || head.next === null) {
        return head;
    }
    
    // 递归到链表末尾,newHead 最终是原链表的尾节点
    const newHead: ListNode | null = reverseListRecursive(head.next);
    
    // 回溯时反转指针方向
    head.next.next = head; // 将下一节点的 next 指向当前节点
    head.next = null;      // 断开当前节点的原始 next 指针
    
    return newHead;
}
/**
 * 1. 双指针
 * 需要注意考虑删除头节点的情况
 * T(n): O(n)
 * S(n): O(1)
 */
function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
    const dummy = new ListNode(0, head) //  在头节点前增加一个没有实际值的辅助节点,用来处理需要删除头节点的情况
    let slow = dummy, fast = head

    while (n--) {
        fast = fast.next
    }

    while (fast) {
        slow = slow.next
        fast = fast.next
    }
    slow.next = slow.next.next

    return dummy.next
};