首页 > 试题广场 >

合并k个已排序的链表

[编程题]合并k个已排序的链表
  • 热度指数:214358 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
合并 k 个升序的链表并将结果作为一个升序链表返回其头节点。

数据范围:节点总数 ,每个节点的val满足
要求:时间复杂度
示例1

输入

[{1,2,3},{4,5,6,7}]

输出

{1,2,3,4,5,6,7}
示例2

输入

[{1,2},{1,4,5},{6}]

输出

{1,1,2,4,5,6}

说明:本题目包含复杂数据结构ListNode,点此查看相关信息
/*
 * function ListNode(x){
 *   this.val = x;
 *   this.next = null;
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param lists ListNode类一维数组
 * @return ListNode类
 */
function mergeKLists(lists) {
    let map = new Map();
    const keys = new Array();
    lists.forEach((tree) => {
        if(tree==null){return false}
        if (tree.val || tree.val == "0") {
            if (map.get(tree.val)) {
                map.set(tree.val, combine(map.get(tree.val), tree));
            } else {
                map.set(tree.val, tree);
                keys.push(tree.val);
            }
        }
    });
    keys.sort((a, b) => {
        return a - b;
    });
    let result = null;
    let needCombine = false;
    let needCombineTree = new ListNode();
    keys.forEach((m, index) => {
        const tree = map.get(m);
        if (needCombine) {
            needCombineTree = combine(tree, needCombineTree);
        } else {
            needCombineTree = tree;
        }
        const lastNode = getLastNode(needCombineTree);
        if (lastNode.val > keys[index + 1]) {
            //说明最后一个值比后面的开始值大,需要进行
            needCombine = true;
        } else {
            needCombine = false;
            if (result == null) {
                result = needCombineTree;
            } else {
                getLastNode(result).next = needCombineTree;
            }
        }
    });
    return result;
}
//插入排序
function combine(tree1, tree2) {
    let temp = new ListNode();
    const header = temp;
    while (tree1 != null && tree2 != null) {
        if (Number(tree1.val) < Number(tree2.val)) {
            temp.val = tree1.val;
            tree1 = tree1.next;
        } else {
            temp.val = tree2.val;
            tree2 = tree2.next;
        }
        temp.next = new ListNode();
        temp = temp.next;
    }
    if (tree1 != null) {
        temp.val = tree1.val;
        temp.next = tree1.next;
    } else if (tree2 != null) {
        temp.val = tree2.val;
        temp.next = tree2.next;
    }
    console.log(header);
    return header;
}

function getLastNode(needCombineTree) {
    while (needCombineTree.next != null) {
        needCombineTree = needCombineTree.next;
    }
    return needCombineTree;
}
module.exports = {
    mergeKLists: mergeKLists,
};

发表于 2023-09-25 17:40:11 回复(0)
/*
 * function ListNode(x){
 *   this.val = x;
 *   this.next = null;
 * }
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param lists ListNode类一维数组
 * @return ListNode类
 */
function mergeKLists( lists ) {
    // write code here
    // 递归调用,将两组链表升序合并为一组
    function Merge(head1,head2){
        if(!head1){
            return head2;
        }
        if(!head2){
            return head1;
        }
        if(head1.val <= head2.val){
            head1.next = Merge(head1.next, head2);
            return head1;
        }else{
            head2.next = Merge(head2.next, head1);
            return head2;
        }
    }
    // 定义空节点接收最后结果
    let node = null;
    // for循环链表数组,每循环一次将会把顺序的两组链表合并为一组拼接到node上
    for(let i = 0; i<lists.length;i++){
        node = Merge(node, lists[i]);
    }
    return node;
}
module.exports = {
    mergeKLists : mergeKLists
};
发表于 2023-06-20 16:17:29 回复(1)
/*
 * function ListNode(x){
 *   this.val = x;
 *   this.next = null;
 * }
 */

/**
 * 
 * @param lists ListNode类一维数组 
 * @return ListNode类
 */
function mergeKListslists ) {
    // write code here
    
    let newHead=null;
    for(let i=0;i<lists.length;i++){
      newHeadMerge(newHead,lists[i]);
    }
    return newHead;
}

function Merge(phead1,phead2){
    if(!phead1){return phead2}
    if(!phead2){return phead1}
    if(phead1.val<=phead2.val){
        phead1.next=Merge(phead1.next,phead2)
        return phead1
    }
    else{
        phead2.next=Merge(phead2.next,phead1)
        return phead2
    }
}
module.exports = {
    mergeKLists : mergeKLists
};
发表于 2022-11-24 20:16:32 回复(0)
// 既然是lists是数组,那就循环遍历,每次找到链表头值最小的那个索引,在进行拼接
function mergeKLists( lists ) {
    let res = new ListNode(0)
    let curr = res
    while(true){
        let idx = -1
        for(index in lists){
            if(lists[index] == null) continue
            else if(idx == -1) idx = index
            else if(lists[index].val < lists[idx].val){
                idx = index
            }
        }
        if(idx == -1) break
        curr = curr.next = lists[idx]
        lists[idx] = lists[idx].next
    }
    return res.next
}

发表于 2022-10-20 10:18:20 回复(0)
/*
 * function ListNode(x){
 *   this.val = x;
 *   this.next = null;
 * }
 */

/**
 * 
 * @param lists ListNode类一维数组 
 * @return ListNode类
 */
function merge( lists, left, right) {
    if (left >= right)
        return lists[left]
    let mid = ~~((left + right) / 2);
    let l = merge( lists, left, mid);//返回左区间指针
    let r = merge( lists, mid + 1, right);//返回右区间指针
    let head = new ListNode(-1);
    let temp = head;
    while (l != null && r != null) {

        if (l.val <= r.val) {
            temp.next = l
            temp = l;
            l = l.next;
        } else {
            temp.next = r
            temp = r;
            r = r.next;
        }
    }
    if (l != null) {
        temp.next = l
    }
    if (r != null) {
        temp.next = r
    }
    return head.next;
}

function mergeKLists(lists) {
   return merge(lists, 0, lists.length - 1);
}
module.exports = {
    mergeKLists : mergeKLists
};

发表于 2022-07-11 00:58:12 回复(0)

主要有两个比较好的方法,一个是堆,一个是分治。

js写这个题。如果使用堆(优先队列)的话,难点是需要自己实现堆的数据结构。c或java好像都有内置已经写好的优先队列数据解构。

js利用数组实现堆需要注意的是:

  1. push添加元素的时候,向数组尾部添加元素,如果向其他位置添加元素的话(比如数组开头),会整个打乱堆,需要重新初始化堆。如果向尾部添加元素,只需要重新初始化树的一半就行。
  2. 如果要删除开头元素。将开头元素后尾部元素交换后在删除尾部元素。因为直接删除打乱了整个堆的解构,需要重新初始化,而删除尾部元素不会打乱堆,可以只初始化一边。
function mergeKLists( lists ) {
    if (lists.length <= 1) return lists[0] || null;
    let heap = new minHeap(), head = {next: null}, p = head;
    for (let i=0; i<lists.length; ++i) {
        if (lists[i]) {
            heap.push(lists[i]);
        }
    }
    while(heap.heap.length) {
        p.next = heap.pop();
        p = p.next;
        if (p.next) {
             heap.push(p.next);
        }
    }
    return head.next;
}
class minHeap {
    constructor() {
        this.heap = [];
    }
    push(node) {
        this.heap.push(node);
        let i = this.heap.length-1, dad = Math.floor((i-1)/2);
        while(dad >= 0) {
            this.minHeap(dad, i);
            dad = Math.floor((dad-1)/2);
        }
    }
    pop() {
        const i=0, j=this.heap.length-1;
        [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]
        const res = this.heap.splice(j, 1);
        this.minHeap(0, j-1);
        return res[0];
    }
    minHeap(l, r) {
        let dad = l, son = dad*2+1;
        if (son > r) return;
        if (son + 1 <= r && this.heap[son+1].val < this.heap[son].val) {
            ++son;
        }
        if (this.heap[son].val < this.heap[dad].val) {
            [this.heap[dad], this.heap[son]] = [this.heap[son], this.heap[dad]]
            this.minHeap(son, r);
        }
    }
}

分治法:

function mergeKLists( lists ) {
    if (lists.length <= 1) return lists[0] || null;
    return merge(lists, 0, lists.length-1);
}
function merge(lists, l, r) {
    if (l > r) return null;
    if (l === r) return lists[l];
    const mid = Math.floor((l+r)/2);
    return mergeTwoList(merge(lists, l, mid), merge(lists, mid+1, r));
}
function mergeTwoList (list1, list2) {
    if (!list1 || !list2) return list1 || list2;
    let p1 = list1, p2 = list2, head = {next: null}, p = head;
    while(p1 && p2) {
        if (p1.val > p2.val) {
            p.next = p2;
            p2 = p2.next;
        } else {
            p.next = p1;
            p1 = p1.next;
        }
        p = p.next;
    }
    p.next = p1 || p2;
    return head.next;
}
发表于 2021-11-26 15:21:15 回复(0)