链表与树

109 阅读2分钟

1、反转链表

链表反转即调整链表的指向,将其反转,遍历链表将每个节点的next指向前一个节点,第一个节点的next置为null。具体代码如下:

function reverseList(head) {
    let prev = null;
    let cur = head;
    while (cur) {
        const next = cur.next;
        cur.next = prev;
        prev = cur;
        cur = next;
    }
    return prev;
}

2、链表相交

链表相交即找到链表最开始相同的节点,并将两条链表相交的节点输出即可,将两个链表头尾相接,分别遍历,只要两条链表有交点,在最后必然会找到那个交点,若无交点,则两链表值都为null,也能退出遍历返回。具体代码如下:

function intersectionList(headA, headB) {
    let pA = headA,
        pB = headB;
    while (pA !== pB) {
        pA = pA === null ? headB : pA.next;
        pB = pB === null ? headA : pB.next;
    }
    return pA;
}

3、旋转链表

将链表向右旋转k个位置,只需k对链表长度取余,减少对应的操作次数,开始旋转时,将链表头尾相连,构成一个环,将链表旋转对应次数后停止旋转,链尾的next置为空即可。具体代码如下:

function rotateList(head, k) {
    if (k === 0 || !head || !head.next) {
        return head;
    }
    let n = 1;
    let cur = head;
    while (cur.next) {
        cur = cur.next;
        n++;
    }

    let add = n - (k % n);
    if (add === n) {
        return head;
    }

    cur.next = head;
    while (add) {
        cur = cur.next;
        add--;
    }

    const ret = cur.next;
    cur.next = null;
    return ret;
}

此题的扩展为 K 个一组翻转链表,整体逻辑类似,进行递归或者迭代操作即可。

4、数据流中的第K大元素

数据流中的第K大元素,按普通排序算法需整体排序,但是那样会浪费过多的空间及时间,故而只需取前K大元素进行排序,后续插入的数字和这K个元素进行对比,大于第K大元素则替换并排序,小于第K大元素则保持不变。具体代码如下:

function KthLargest() {
    this.list = [];
    this.k = k;
    nums.sort((a, b) => a - b);
    for (let i = nums.length - 1; i > nums.length - 1 - k && i >= 0; i--) {
        this.list.push(nums[i]);
    }
    return null;
}
KthLargest.prototype.add = function (val) {
    if (this.list.length === 0) {
        this.list.push(val);
    } else if (this.list.length < this.k) {
        poll(this.list, val, this.k);
    } else if (val >= this.list[0]) {
        this.list.unshift(val);
        this.list.pop();
    } else if (val > this.list[this.list.length - 1]) {
        poll(this.list, val, this.k);
    }
    return this.list[this.k - 1] || null;
};

function poll(list, val, k) {
    let temp = val;
    let i;
    if (list.length < k) {
        list.push(val);
        list.sort((a, b) => b - a);
        return;
    }
    for (i = list.length - 1; i >= 0; i--) {
        if (list[i] >= temp) {
            list[i + 1] = temp;
            break;
        } else {
            list[i] = list[i - 1];
        }
    }
}

5、反转二叉树

二叉树反转使用简单的递归操作即可。具体代码如下:

function invertTree(root) {
    if (root === null) {
        return null;
    }
    const left = invertTree(root.left);
    const right = invertTree(root.right);
    root.left = right;
    root.right = left;
    return root;
}