Skip to content

链表

【LeetCode 直通车】:234 回文链表(简单)

  1. 我们遍历出数组后将其反转对比即可
javascript

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var isPalindrome = function(head) {
    const arr = [];
    let cur = head;
    while(cur) {
        arr.push(cur.val);
        cur = cur.next;
    }
    let arr1 = arr.slice().reverse();
    return arr.join('') === arr1.join('')    
};
  1. 获取后使用双指针
javascript
var isPalindrome = function (head) {
    const arr = [];
    let cur = head;
    while (cur) {
        arr.push(cur.val);
        cur = cur.next;
    }
    let left = 0, right = arr.length -1;

    while(left < right) {
        if(arr[left] !== arr[right]) return false;
        left++;
        right--;
    }

    return true
};
  1. 直接反转链表后进行比较
javascript

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var isPalindrome = function(head) {
    const copyList = (list) => {
        let cur = list
        let dummy = new ListNode();
        let curnode = dummy;
        while(cur) {
            curnode.next = new ListNode(cur.val, cur.next);
            cur = cur.next;
            curnode = curnode.next;
        }

        return dummy.next;
    }
    const reverseList = (list) => {
        let dummy = list;
        let pre = null;
        let cur = dummy;
        
        while(cur) {
            const next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next
        }
        return pre;
    }
    const copylist = copyList(head);
    const reverselist = reverseList(head);

    let l1 = copylist, l2 = reverselist;
    while(l1 && l2) {
        if(l1.val !== l2.val) return false;
        l1 = l1.next;
        l2 = l2.next;
    }
    return true
};
  1. 快慢指针 反转 slow 后面的 链表与之前的对比即可 边界处理 奇偶问题
javascript

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var isPalindrome = function (head) {
    let slow = head, fast= head, l1 = head;

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

    let l2 = reverseList(slow.next);
    while(l2) {
        if(l1.val !== l2.val) return false;
        l1 = l1.next;
        l2 = l2.next;
    }
    return true

};

const reverseList = (list) => {
    let pre = null, cur = list;
    while(cur) {
        const next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }
    return pre
}

👉 【LeetCode 直通车】:206 反转链表(简单)

这个在上面已经用到了, 就是借助中间变量 pre 以及 cur 来进行实现

javascript
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    let cur = head;
    let pre = null;
    while(cur) {
        const next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next
    }
    return pre;
};

👉 【LeetCode 直通车】:141 环形链表(简单)

环形列表使用快慢指针, 如果是环形那么他们一定会相遇

javascript

/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function(head) {
    let slow = head, fast = head;
    while(fast && fast.next) {
        slow = slow.next;
        fast = fast.next.next;
        if(slow === fast) return true;
    }
    return false
};

把我笑死的解法

JSON.stringify(head) 秒杀法😃 除非不报错,报错就是有环!!

javascript
var hasCycle = function (head) {
    try {
        JSON.stringify(head)
    } catch{
        return true
    }
    return false
};

👉 【LeetCode 直通车】:160 相交链表(简单)

链表🍌的逻辑就是 p1 +p2 = p2 + p1 所以所以让 p1 走完走p2的路即可 相等🐔🍌

javascript

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
    let l1 = headA, l2 = headB;
    while(l1 !== l2) {
        l1 = l1 ? l1.next : headB;
        l2 = l2 ? l2.next : headA;
    }
    return l1
};

合并两个有序链表

javascript
/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
var mergeTwoLists = function(list1, list2) {
    let list = new ListNode();
    let dummy = list;
    let l1 = list1, l2 = list2;

    while(l1&&l2) {
        if(l1.val < l2.val) {
            dummy.next = l1;
            l1 = l1.next
        } else {
            dummy.next = l2;
            l2 = l2.next
        }
        dummy = dummy.next;
    }
    dummy.next = l1 ?? l2;
    return list.next;
};

👉 【LeetCode 直通车】:148 排序链表(中等)

合并有序最终可排序 所以将链表拆分成最小单位 1 然后进行合并即可

javascript
var mergeTwoLists = function(list1, list2) {
    let dummyHead = new ListNode();
    let l1 = list1, l2 =list2, dummy = dummyHead;
    while(l1 && l2) {
        if(l1.val < l2.val) {
            dummy.next = l1;
            l1 = l1.next
        } else {
            dummy.next = l2;
            l2 = l2.next;
        }
        dummy = dummy.next;
    }
    dummy.next = l1 ?? l2;
    return dummyHead.next
};

const getHead = (subLength, curr) => {
    let head = curr;
    for (let i = 1; i < subLength && curr && curr.next; i++) {
        curr = curr.next;
    }
    let nextHead = null;
    if (curr !== null) {
        nextHead = curr.next;
        curr.next = null;
    }
    return [head, nextHead]
}

var sortList = function (head) {
    if (!head) return head;
    let length = 0;
    let node = head;
    while (node) {
        length++;
        node = node.next;
    }
    const dummyHead = new ListNode(0, head);
    for (let subLength = 1; subLength < length; subLength <<= 1) {
        let prev = dummyHead, curr = dummyHead.next;
        while (curr !== null) {
            let head1, head2, nextHead;
            [head1, nextHead] = getHead(subLength, curr)
            curr = nextHead;
            [head2, nextHead] = getHead(subLength, curr);
            curr = nextHead;
            const merged = mergeTwoLists(head1, head2);
            prev.next = merged;
            while (prev.next !== null) {
                prev = prev.next;
            }
        }
    }
    return dummyHead.next;
};

👉 【LeetCode 直通车】:23 合并K个升序链表(困难)

分治 或者两辆合并即可

javascript
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function(lists) {
    if(!lists.length) return null
    while(lists.length>1) {
        lists[0] = merge(lists[0], lists[1]);
        lists.splice(1,1,)
    }
    return lists[0]
};


const merge = (list1, list2) => {
    const dummyHead = new ListNode();
    let dummy = dummyHead, l1 = list1, l2 = list2;
    while(l1 && l2) {
        if(l1.val < l2.val) {
            dummy.next = l1;
            l1 = l1.next
        } else {
            dummy.next = l2;
            l2 = l2.next;
        }
        dummy = dummy.next
    }
    dummy.next = l1 ?? l2;
    return dummyHead.next;
}

/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function(lists) {
// 合并从 lists[i] 到 lists[j-1] 的链表
    function dfs(i, j) {
        const m = j - i;
        if (m === 0) return null; // 注意输入的 lists 可能是空的
        if (m === 1) return lists[i]; // 无需合并,直接返回
        const left = dfs(i, i + (m >> 1)); // 合并左半部分
        const right = dfs(i + (m >> 1), j); // 合并右半部分
        return merge(left, right); // 最后把左半和右半合并
    }
    return dfs(0, lists.length);
};

👉 【LeetCode 直通车】:25 K 个一组翻转链表(困难)

javascript
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var reverseKGroup = function(head, k) {
    const dummyHead = new ListNode(0, head);
    let pre = dummyHead;
    while(head) {
        let tail = pre;
        for(let i = 0; i < k; i++) {
            tail = tail.next;
            if(!tail) {
                return dummyHead.next;
            }
        }
        const next = tail.next;
        [head, tail] = reverseList(head, tail);
        pre.next = head;
        tail.next = next;
        pre = tail;
        head = tail.next;
    }
    return dummyHead.next;
};

const reverseList = (head, tail) => {
  let pre = tail.next;
  let cur = head;
  while(pre !== tail) {
    const next = cur.next;
    cur.next = pre;
    pre = cur;
    cur = next;
  }
  return [tail, head]
}