首页 > 其他分享 >Leetcode 21-25题

Leetcode 21-25题

时间:2024-02-19 20:36:29浏览次数:21  
标签:25 head ListNode 21 auto next 链表 括号 Leetcode

合并两个有序链表

将两个升序链表合并为一个新的升序链表。

用两个指针指向两个链表的表头,然后每次比较一下哪个值小,将较小的节点接到答案后面即可。

ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
    auto dummy = new ListNode(), p = dummy;
    auto l1 = list1, l2 = list2;
    while(l1 && l2) {   // 当l1和l2都不为空才进入循环
        if(l1->val <= l2->val) {
            p->next = l1;   // 将l1节点接到答案尾部
            p = p->next;    // 将答案和l1后移
            l1 = l1->next;
        }else {
            p->next = l2;
            p = p->next;
            l2 = l2->next;
        }
    }
    if(l1)  p->next = l1;
    if(l2)  p->next = l2;
    return dummy->next;
}

括号生成

有\(n\)对括号,生成所有可能并且有效的括号组合。

有效的就是要满足任意前缀中左括号的数量一定大于等于右括号的数量。

然后做DFS,每次递归时都要保证左括号数量大于等于右括号数量。

也就是说,只有左括号数量大于右括号数量时,才可以放右括号。(前提是还有右括号可以放)

vector<string> ans;

void dfs(int n, int l, int r, string path) {
    if(l == n && r == n) {          // 左右括号都放满了则输出
        ans.push_back(path);
        return ;
    }
    if(l != n)  dfs(n, l + 1, r, path + "(");       // 若有左括号就可以直接放
    if(r != n && l > r) dfs(n, l, r + 1, path + ")");   // 若有右括号且前缀中左括号数量严格大于右括号数量则可以放
}

vector<string> generateParenthesis(int n) {
    dfs(n, 0, 0, "");
    return ans;
}

合并K个升序链表

给定一个链表数组,每个链表均为升序排列,将所有链表合并到一个升序链表中。

本质上和合并两个有序链表相似,即每次找最小的节点并接到答案后面。但是这样每次找会有\(O(k)\)的比较次数。

因此可以采用堆优化来查找最小值,即每次把每个链表都存一个节点到堆中,取最小值接到答案后面,是\(O(1)\)的比较次数。

优先队列默认是大根堆,要重载小于号才能变成小根堆,如priority_queue<int, vector< int>, greater< int>> q;

若要重载其他数据结构的小于比较,需要仿函数来重载。

struct cmp {
    bool operator() (ListNode* a, ListNode* b) {    // 仿函数
        return a->val > b->val;                     // 重载为大于
    }
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
    auto dummy = new ListNode(), p = dummy;
    priority_queue<ListNode*, vector<ListNode*>, cmp> heap;

    for(auto list : lists)  
        if(list)    heap.push(list);    // 样例2中有空链表
    while(!heap.empty()) {
        auto list = heap.top();         // 队头是最小的节点
        heap.pop();

        p->next = list;
        p = p->next;
        if(list->next)  heap.push(list->next);
    }
    return dummy->next;
}

两两交换链表中的节点

两两交换链表中相邻的节点,并返回交换后链表的头节点。

所有链表题,只要涉及到头节点的判断问题,都可以加一个虚拟头节点

head -> 1 -> 2 -> 3 -> 4 -> tail
head -> 2 -> 1 -> 3 -> 4 -> tail

要实现上述链表的两两交换,比如要交换1和2节点,需要将head指向2,将1指向3,将2指向1,实现这三步即可。

i -> j -> k -> l
交换j和k
i->next = k
j->next = k->next
k->next = j
ListNode* swapPairs(ListNode* head) {
    auto dummy = new ListNode(-1, head), p = dummy;
    while(p->next && p->next->next) {
        // p -> a -> b
        auto a = p->next, b = a->next;
        p->next = b;
        a->next = b->next;
        b->next = a;
        if(p->next->next)   p = p->next->next;
    }
    return dummy->next;
}

K个一组翻转链表

将链表每\(k\)个节点一组进行翻转,返回修改后的链表。如果节点总数不是\(k\)的整数倍,最后剩余的节点保持原有顺序。

head -> 1 -> 2 -> 3 -> 4 -> 5 -> tail
head -> 4 -> 3 -> 2 -> 1 -> 5 -> tail
head    1 <- 2 <- 3 <- 4    5 -> tail
		a    b
			 a    b
			 	  a    b

我们采取这样的策略,先改变内部的方向,内部都更改完之后,再更改两边的指向关系,如下代码和示意图:

ListNode* reverseKGroup(ListNode* head, int k) {
    auto dummy = new ListNode(-1, head);
    for (auto p = dummy;;) {
        auto q = p;
        for (int i = 0; i < k && q; i ++ ) q = q->next;
        if (!q) break;      // 以上为判断后面是否还有k个元素

        // head -> 1 -> 2 -> 3 -> 4 -> 5 -> tail
        //    p    a    b
        //    p         a    b
        //    p              a    b
        auto a = p->next, b = a->next;
        for (int i = 0; i < k - 1; i ++ ) {
            // a -> b -> c
            auto c = b->next;
            // a <- b  c
            b->next = a;
            // 移动到下一轮更改的位置
            a = b, b = c;
        }
        // head    1 <- 2 <- 3 <- 4    5 -> tail
        //    p    c              a    b
        // head    4 -> 3 -> 2 -> 1    5 -> tail
        //    p    a              c    b
        auto c = p->next;
        p->next = a, c->next = b;
        // head -> 4 -> 3 -> 2 -> 1 -> 5 -> tail
        //                        p
        p = c;
    }
    return dummy->next;
}

标签:25,head,ListNode,21,auto,next,链表,括号,Leetcode
From: https://www.cnblogs.com/xushengxiang/p/18021889

相关文章

  • 【linux新手起步02】vi编辑时出现E325:ATTENTION。
    vi编辑时出现E325:ATTENTION一、原因二、解决方法:rm+swap文件路径以及名称一.原因:出现这个问题,是因为由于在编辑该文件的时候异常退出,因为vim在编辑文件时会创建一个交换文件swapfile以保证文件的安全性。点击查看代码E325:ATTENTIONFoundaswapfilebythen......
  • P2524 Uim的情人节礼物•其之弐 题解
    题目描述前传:详见洛谷P2525Uim成功地按照顺序将礼物送到了 N 个妹子的手里并维持她们的和谐。现在Uim现在想知道,他最终选择的顺序是所有给 N 个妹子送礼顺序中,字典序第几小的。送礼顺序可以看作1,2,⋯,N 的一个排列。输入格式第一行一个整数N,表示有 N 个数。第二......
  • 20240219总结
    P9994[YnoiEasyRound2024]TEST_132根号分治。考虑修改操作。如果修改的x数量大于阙值B,那么打上操作次数标记,否则直接各自修改对应的\(y_i\)答案。查询时对于一个y,记录下所有使得xi数量大于B且yi=y的i,这一些贡献是没有加上的。显然xi的数量<=n/B,对于每一个这样的xi快速......
  • 21 - 数值类型
    常见内置数值类型数值类型是不可变类型(immutabletype),它包括布尔类型、整数、浮点数与复数。类型英文名构造方式对应关键字构造函数布尔Booleanvar=Trueboolbool()整数Integervar=5intint()浮点数Floatvar=5.0floatfloat()复数Comple......
  • 微软 Office 2021 专业增强版,安装完自动激活
    123盘下载地址  MicrosoftOffice2021VL官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘(123pan.com)安装前先关闭windows系统自带的 病毒  微软办公软件套件MicrosoftOfficeLTSC2021专业增强版2024年01月批量许可版更新推送!Office2021正式版和Windows11......
  • 报废车综合管理系统 系统源码加微信820688215 获取商业授权 体验官方地址 www.lvxun.v
    报废车综合管理系统系统源码加微信820688215获取商业授权体验官方地址 www.lvxun.vip  ......
  • 2021/1/14
    可以看出,for循环是将字符串的内容:依次取出所以,for循环也被称之为:遍历循环 同while循环不同,for循环是无法定义循环条件的只能从被处理的数据集中,依次取出内容进行处理所以,理论上讲,Python的for循环无法构建无限循环(被处理的数据集不可能无限大 range语句语法1:range(nu......
  • Porsche Piwis 3 Tester III V43.300.22 + V38.250 Diagnostic Tool Support Diagnosi
    Greatnews!ThePorschePiwis3TesterIIIV43.300.22+V38.250DiagnosticToolhasjustbeenupdatedwithnewsoftwareversions.ThislatestversioncoversalloldandnewPorschecarsupto2024,makingitacomprehensivediagnostictoolforprofessiona......
  • Leetcode 16-20题
    最接近的三数之和给定整数数组和目标值target,从数组中选出三个整数,使得和与target最接近,并返回三数之和。保证恰好存在一个解。和上一题类似,我们先对整数数组排序,然后固定i,枚举j,找到满足nums[i]+nums[j]+nums[k]>=target的最小的k。那么显然有nums[i]+nums[j]+nums[k-1]<targ......
  • P9847 [ICPC2021 Nanjing R] Crystalfly
    前景导入当\(t\in[1,2]\)时,本题如何求解?答:树形dp设\(f[i]\)为以\(i\)为根的树,根节点的晶蝶已消散且儿子节点的晶蝶还未被惊动,能获得的最大晶蝶数。则有状态转移方程\(f[i]=(\sumf[u])+max(a[u])\),其中\(u\)为\(i\)的儿子。最终的答案即为\(f[1]+a[1]\)划向更......