牛客-C语言解法-合并k个已排序的链表

 题目链接:

合并k个已排序的链表_牛客题霸_牛客网 (nowcoder.com)

题目简介:

描述

合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。

数据范围:节点总数 0≤n≤5000,每个节点的val满足 ∣val∣<=1000

要求:时间复杂度 O(nlogn)

题目解法:

#include "stdio.h"
#include "stdlib.h"


/*
 *BM5 合并k个已排序的链表
描述
    合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。

数据范围:节点总数  0≤n≤5000,每个节点的val满足 |val| <= 1000
要求:时间复杂度 O(nlogn)O(nlogn)

如输入[{1,2,3},{4,5,6,7}]时,返回{1,2,3,4,5,6,7},
*/

/**************************code*****************************************/
 struct ListNode {
	int val;
	struct ListNode *next;
 };

/**
 * 
 * @param lists ListNode类一维数组 
 * @param listsLen int lists数组长度
 * @return ListNode类
 */
//根据索引获得链表的元素
int getListElemByIndex(struct ListNode* list, int index){
    for(int i=0; i<index; i++)
        list = list->next;
    return list->val;
}

//计算数组指定长度的前N项和
int getSumLen(int *eachLen, int listsLen){
    int sumLen = 0;
    for(int i=0; i<listsLen; i++){
        sumLen += eachLen[i];
    }
    return sumLen;
}
//找到链表首部最小的值,并返回链表索引
int findListHeadMin(struct ListNode** lists, int listsLen, int* eachIndex, int* eachLen){
    int listIndex = 0;
    int listNodeMin = 1001;
    int tmpVal;
    struct ListNode* tmpList;
    for(int i=0; i<listsLen; i++){
        if(eachIndex[i] >= eachLen[i])continue; //如果该链表已经用完,跳过
        
        tmpVal = getListElemByIndex(lists[i], eachIndex[i]);
        if(tmpVal < listNodeMin){
            listNodeMin = tmpVal;
            listIndex = i;
        }
    }
    return listIndex;
}

struct ListNode* mergeKLists(struct ListNode** lists, int listsLen ) {
    // write code here
    struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* tmpNode = dummyHead;
    int *eachLen = (int*)malloc(sizeof(int)*listsLen);  //保存各个链表的长度
    int *eachIndex = (int*)malloc(sizeof(int)*listsLen);  //保存各个链表的索引
    int sumLen = 0;//各个链表相加的总长度
    int listMinIndex; //各个链表中当前节点值最小的链表索引

    for(int i=0; i<listsLen; i++){      //获得各个链表的长度
        int len = 0;
        eachLen[i] = 0;
        eachIndex[i] = 0;           //清空索引
        struct ListNode* tmp = *(lists + i);
        while(tmp){
            eachLen[i]++;
            tmp = tmp->next;
        }
    }
    sumLen = getSumLen(eachLen, listsLen);  //计算各个链表的元素总和
    if(sumLen == 0) return NULL;            //如果 0个链表 或者 有多个链表但每个链表都为空,则返回NULL
    for(int curLen=0; curLen<sumLen; curLen++){ //根据元素总和进行循环
        tmpNode->val = 0;               //先初始化当前链表值

        listMinIndex = findListHeadMin(lists, listsLen, eachIndex, eachLen);    //找到各个链表中未使用的首元素最小的链表索引
        tmpNode->val = getListElemByIndex(lists[listMinIndex], eachIndex[listMinIndex]);    //根据链表以及链表索引找到未使用的元素
        eachIndex[listMinIndex]++;                      //记录当前链表已使用的元素数量,方便findListHeadMin函数判断未使用的元素以及是否到末尾了

        if(curLen==sumLen-1)continue;           //如果已经到最后一个元素,那么不再申请节点
        tmpNode->next = (struct ListNode*)malloc(sizeof(struct ListNode));    //初始化新节点
        tmpNode = tmpNode->next;    //指向下一个节点
    }

    return dummyHead;
}

/**************************end******************************************/

int main ()
{
    struct ListNode LN13={3,NULL};
    struct ListNode LN12={2,&LN13};
    struct ListNode LN1 ={1,&LN12};

    struct ListNode LN24={7,NULL};
    struct ListNode LN23={6,&LN24};
    struct ListNode LN22={5,&LN23};
    struct ListNode LN2 ={4,&LN22};
    struct ListNode *input1[2] = {&LN1, &LN2};
    
    struct ListNode LN33={3,NULL};
    struct ListNode LN32={2,&LN33};
    struct ListNode LN3 ={1,&LN32};

    struct ListNode LN43={3,NULL};
    struct ListNode LN42={3,&LN43};
    struct ListNode LN4 ={3,&LN42};

    struct ListNode *pLN = mergeKLists(input1, 2);

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值