leetcode-143-重排链表

题意描述:

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:

L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

leetcode-143-重排链表_第1张图片

解题思路:
Alice: 这题看起来有点简单啊。
Bob: 之间把每个链表节点的位置存到数组里面,然后双指针从两个方向去读,修改节点之间的指向关系就行了。
Alice: 需要注意的时候,末尾节点的 next 要改成 null
Bob: 这种方法能过的,就是要注意处理一下细节。
Alice: 我看到还有别的方法可以做的,搞得是什么双指针,中间节点,翻转链表合并链表那一套。
Bob: 中间节点 ?中间节点到这里倒是一定会变成末尾节点。如果是偶数个怎么办 ?偶数个没有中间节点的 ?
Alice: 那就是这时候是没有中间节点的,我好像明白了,双指针就是快慢双指针,且速度差是 1,这样一个到末尾的时候,一个刚好到中间。
Bob: 原来是这样,翻转链表和合并链表没啥好讲的了,属于是链表的基本操作了。
Alice: 有个问题,翻转链表的递归写法会爆栈吗 ?
Bob: 应该不会吧,只是修改指向关系而已。
Alice: 我去试试。递归翻转链表的内存使用率有点高啊,只超过了 6% 的人。
Bob: 还能改成循环 ??
Alice: 是啊,翻转链表还能改成循环。我想了好一会呢。

const revertLink = (headNode: ListNode) => {
        let prepre = null;
        let pre = headNode;
        let current = headNode.next
        while(current) {
            // 翻转
            pre.next = prepre;
            prepre = pre;
            pre = current;
            // 继续
            current = current.next;
        }
        pre.next = prepre;
        return pre;
    }

Bob: o( ̄▽ ̄)d good


代码:

typescript 存储链表节点

function reorderList(head: ListNode | null): void {
    const nodeListAddress = [];
    let temp = head;
    while(temp){
        nodeListAddress.push(temp);
        temp = temp.next;
    }
    let left = 0;
    let right = nodeListAddress.length - 1;

    let pre = null;
    while(left < right) {
        if(pre) {
            pre.next = nodeListAddress[left];
        }
        nodeListAddress[left].next = nodeListAddress[right];
        pre = nodeListAddress[right];
        left++;
        right--;
    }
    if(left === right && pre) {
        pre.next = nodeListAddress[left];
        pre = nodeListAddress[left];
        left++;
        right--;
    }
    // 尾节点
    if(pre) {
        pre.next = null;
    }
    
};

typescript 链表中点 + 翻转链表 + 合并链表


function reorderList(head: ListNode | null): void {

    // 边界条件
    if(!head.next) {
        return;
    }
    // 快慢指针找到中间节点
    const getMiddleNode = (headNode: ListNode) => {
        // 从 headNode 开始
        let fast = headNode;
        let slow = headNode;
        let preSlow = null;
        while(fast.next){
            fast = fast.next;
            if(fast.next) {
                fast = fast.next
            } 
            preSlow = slow;
            slow  = slow.next;

        }
        return preSlow;
    }

    const revertLink = (headNode: ListNode) => {
        // 递归终点
        if(headNode.next === null) {
            return headNode;
        } else {
            const ret = revertLink(headNode.next);
            headNode.next.next = headNode;
            return ret;
        }
    }

    const mergeLink = (left: ListNode, right: ListNode) => {
        let current = left;
        left = left.next;
        while(left || right) {
            if(right) {
                current.next = right;
                current = current.next;
                right = right.next;
            }
            if(left) {
                current.next = left;
                current = current.next;
                left = left.next;
            }
        }
    }



    const leftEnd = getMiddleNode(head);
    const rightStart = leftEnd.next;
    const right = revertLink(rightStart);
    // 斩断两个链表之间的联系
    leftEnd.next = null;
    rightStart.next = null;
    mergeLink(head, right);
};

测试用例:

[1000]

参考:

  • 题目链接

你可能感兴趣的:(leetcode,链表)