链表学习Leetcode刷题记录(9_30)(补)

题目:

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []
输出:[]

1.面对多个长短不一的链表,加上力扣直接给的如下函数,上来我就懵了,我寻思上一题是合并两个链表,这上来直接让我合并n个有点吓人,还有个没听过的vector,于是果断点开"题解"

    ListNode* mergeKLists(std::vector<ListNode*>& lists) 

2.代码如下

class Solution {
public:
    ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
        if ((!a) || (!b)) return a ? a : b;
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) {
                tail->next = aPtr; aPtr = aPtr->next;
            } else {
                tail->next = bPtr; bPtr = bPtr->next;
            }
            tail = tail->next;
        }
        tail->next = (aPtr ? aPtr : bPtr);
        return head.next;
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *ans = nullptr;
        for (size_t i = 0; i < lists.size(); ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }
};

 但是这串代码并不是贴在开头的,反而开头讲解了按升序合并两个链表的一般方法(相较于上一题的递归)

3.一般方法如下

ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
    if ((!a) || (!b)) return a ? a : b;
    ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
    while (aPtr && bPtr) {
        if (aPtr->val < bPtr->val) {
            tail->next = aPtr; aPtr = aPtr->next;
        } else {
            tail->next = bPtr; bPtr = bPtr->next;
        }
        tail = tail->next;
    }
    tail->next = (aPtr ? aPtr : bPtr);
    return head.next;
}

先创建一个指针,指向最终链表的头指针,即头指针的前一位,对两个链表进行对比,哪个链表的元素小就放到tail后面,直到一个链表为空停止,把剩下的接上,最后返回head的next

4.有了上述步骤就简单多了,把这个mergetwoLists放到mergeKLists里,然后循环就结束了

5.力扣的题解还是有点不严谨,这是经AI修改后的代码

    ListNode* mergeKLists(std::vector<ListNode*>& lists) {
        if (lists.empty()) return nullptr; // 如果列表为空,返回 nullptr
        
        ListNode* ans = lists[0]; // 将 ans 初始化为第一个链表

        for (size_t i = 1; i < lists.size(); ++i) {
            ans = mergeTwoLists(ans, lists[i]); // 合并每个链表
        }

        return ans; // 返回合并后的链表
    }

将ans初始化为nullptr可能会导致mergetwoLists出现问题,故用empty函数检查链表,如果空,返回nullptr即可,而将ans初始化为第一个链表更合理。

6.补充一下std::vector的用法

在 C++ 中,std::vector是一个动态数组容器,它允许你存储一系列元素,并且可以随时修改其大小。std::vector<ListNode*>表示一个存储指向 ListNode对象的指针的动态数组。在这个问题中,lists是一个 std::vector<ListNode*>,用于存储多个链表的头节点指针。

主要用法:

1.声明:你可以声明一个 vector,例如:

  std::vector<ListNode*> lists;


  这声明了一个空的 std::vector,它存储的是 ListNode* 类型(即链表节点指针)的元素。

2.添加元素:你可以使用 `push_back` 方法将元素添加到 `vector` 中:

  lists.push_back(list1);
  lists.push_back(list2);


  这里,list1 和 list2 是指向链表的指针,它们会被添加到 lists 中。

3.访问元素:你可以通过下标或者迭代器访问 `vector` 中的元素:
 

  ListNode* head = lists[0];  // 访问第一个链表

4.遍历:你可以使用范围 for 循环或传统的 for 循环来遍历 vector 中的元素:
 

  for (auto list : lists) {
      // 对每个链表的头节点进行操作
  }

5.修改元素:你可以直接修改 vector 中的元素,前提是这些元素是指针或者对象:
 

lists[0] = new_head;  // 修改第一个链表的头节点

6.大小:你可以使用 size() 方法来获取 vector 中元素的个数:
 

  size_t size = lists.size();

总结:
std::vector 是 C++ 中非常常用的容器类,它可以存储多个元素,提供动态调整大小的能力。在这里,它被用来存储多个链表的头节点指针。你可以灵活地向 vector 中添加、访问和修改元素,同时可以利用其内置的高效操作来简化代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值