链表类型题目

文章目录

  • 简介
  • 链表的常用技巧
  • 两数相加
    • 原理
    • 代码
    • 代码||
  • 两两交换链表中的节点
    • 代码
    • 原理
  • 重排链表(重要)
    • 原理
    • 代码
  • 合并 K 个升序链表
    • 代码
    • 递归代码
  • K 个一组翻转链表
    • 原理
    • 代码

简介

大家好,这里是jiantaoyab,这篇文章给大家带来的是链表相关的题目练习和解析,希望大家能相互讨论进步


链表的常用技巧

  • 画图

画图能更加清晰,方便我们去理解

  • 引入虚拟的头结点

创建新的头结点指向原来的链表,方便处理边界情况

  • 多定义一个变量

多定义一个next就不用考虑先链接谁的问题

  • 快慢双指针
  1. 判断链表中是否有环
  2. 找环的入口
  3. 找链表倒数第n个节点
  • 链表逆序用头插

两数相加

https://leetcode.cn/problems/add-two-numbers/

https://leetcode.cn/problems/lMSNwu/ 两数相加||

原理

在这里插入图片描述

代码

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* new_head = new ListNode(0); //创建哨兵位头结点
        ListNode* tail = new_head;
        int x = 0;//记录进位
    
        ListNode* cur1 = l1, *cur2 = l2;
        while(cur1 || cur2 || x)
        {
            if(cur1)
            {
                x += cur1->val;
                cur1 = cur1->next;
            }
            if(cur2)
            {
                x += cur2->val;
                cur2= cur2->next;
            }
            tail->next = new ListNode(x % 10);
            tail = tail->next;
            x /= 10;
        }
        tail =  new_head->next;
        delete new_head;
        return tail;
        
    }
};

代码||

class Solution {
public:
 ListNode* ReserveList(ListNode* head) {
        ListNode * head= nullptr;
        ListNode * curr = head;
        while(curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* new_head = new ListNode(0); //创建哨兵位头结点
        ListNode* tail = new_head;
        int x = 0;//记录进位
        l1 = ReserveList(l1);
        l2 = ReserveList(l2);
        ListNode* cur1 = l1, *cur2 = l2;
        while(cur1 || cur2 || x)
        {
            if(cur1)
            {
                x += cur1->val;
                cur1 = cur1->next;
            }
            if(cur2)
            {
                x += cur2->val;
                cur2= cur2->next;
            }
            tail->next = new ListNode(x % 10);
            tail = tail->next;
            x /= 10;
        }
        tail =  new_head->next;
        tail = ReserveList(tail);
        delete new_head;
        return tail;
    }
};

两两交换链表中的节点

https://leetcode.cn/problems/swap-nodes-in-pairs/

代码

  • 递归的方式

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //终止条件是链表只有一个节点 / 链表中没有节点
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* nnext =  swapPairs(head->next->next);
        ListNode* newhead = head->next;
        newhead->next = head;
        head->next = nnext;
        return newhead;
    }
};
  • 迭代的方式

原理

在这里插入图片描述

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        // 0个和1个节点直接返回就好
       if(head == nullptr || head->next == nullptr)  return head;
       ListNode* newhead = new ListNode(0); //哨兵位头结点
       newhead->next = head;
       ListNode* prev =newhead;
       ListNode* cur = prev->next;
       ListNode* next = cur->next;
       ListNode* nnext = next->next;
       while(cur != nullptr && next != nullptr)
        {
            //交换节点
            prev->next = next;
            next ->next = cur;
            cur ->next = nnext;

            //更新位置
            prev = cur;
            cur = nnext;
            if(cur != nullptr)
             next = cur->next;
            if(next != nullptr)
              nnext = next->next;
            
           
        }
        cur = newhead->next;
        delete newhead;
        return cur;
    }
};

重排链表(重要)


https://leetcode.cn/problems/LGjMqU/

原理

在这里插入图片描述

代码

class Solution {
public:
    void reorderList(ListNode* head) {
        // <=2节点的直接返回
        if(head == nullptr || head->next == nullptr || head->next->next ==nullptr) return ;
        //1.找到链表的中间节点
        ListNode * slow = head, *fast = head;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        //2.将后半部分链表逆置
        ListNode* new_head = new ListNode(0);
        ListNode* cur = slow->next;     
        slow->next = nullptr; //断开链表
        while(cur)
        {
           ListNode* next = cur->next;
           cur->next = new_head->next;
           new_head->next = cur;
           cur = next;
        }
        //3.合并2个链表
        ListNode* ret_head = new ListNode(0);
        ListNode* prev = ret_head;
        ListNode* cur1 =head, *cur2 = new_head->next;
        while(cur1)
        {
           //先放第一个链表
           prev->next = cur1;
           cur1 = cur1->next;
           prev = prev->next;
           //再放第二个链表
           if(cur2)
           {
               prev->next = cur2;
               cur2 = cur2->next;
               prev = prev->next;
           }
        }
        delete new_head;
        delete ret_head;
    }
};

合并 K 个升序链表

https://leetcode.cn/problems/vvXgSW/

代码

class Solution {

    struct cmp 
    {
        bool operator() (const ListNode* l1, const ListNode* l2) 
        {
            return l1->val > l2->val;
        }
    };

public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        //创建小根堆
        priority_queue<ListNode* ,vector<ListNode*>,cmp> heap;

        //让所有链表的头结点加入到小根堆中
        for(auto l :lists)
        {
            if(l) heap.push(l);
        }

        //合并k个有序链表
        ListNode* new_head = new ListNode(0);
        ListNode* prev = new_head;
        //小根堆中还有元素说明还有链表没到nullptr
        while(!heap.empty())
        {
            ListNode* min = heap.top();
            heap.pop();
            prev->next = min;
            prev = min;
            if(min->next) heap.push(min->next);
        }
        prev->next = nullptr;
        prev = new_head->next;
        delete new_head;
        return prev;
    }
};

//自己用vs调试的时候,可以加上下面代码调试一步一步看
int main()
{
	vector<ListNode*> lists = { new ListNode(1, new ListNode(4, new ListNode(5))),
		new ListNode(1, new ListNode(3, new ListNode(4))),
		new ListNode(2, new ListNode(6)) };
	mergeKLists(lists);
}

递归代码

class Solution {
public:
      ListNode* MergeTowList(ListNode* l ,ListNode* r)
      {
          if(l == nullptr) return r;
          if(r == nullptr) return l;
          ListNode new_head ;
          new_head.next = nullptr;
          ListNode* cur1 = l, *cur2 = r, *prev = &new_head ;
          while(cur1 && cur2)
          {
              if(cur1->val >= cur2->val)
              {
                prev = prev->next = cur2;
                cur2 = cur2->next;
              }
              else
              {
                prev = prev->next = cur1;
                cur1 = cur1->next;
              }
          }
          if(cur1) prev->next =cur1;
          if(cur2) prev->next =cur2;
          return new_head.next;
      }
     ListNode* Merge(vector<ListNode*>& lists, int left, int right) 
     {
         if(left > right) return nullptr;
         if(left == right) return lists[left];
         int mid = (left + right) >> 1;
         ListNode* l = Merge(lists, left, mid); 
         ListNode* r = Merge(lists, mid + 1, right); 
        //合并2个有序链表
        return MergeTowList(l,r);
     }
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {      
        return Merge(lists, 0, lists.size() - 1);
    }
};

K 个一组翻转链表

原理

在这里插入图片描述

代码

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
     
        int N = 0;
        ListNode * p = head;
        while(p)
        {
            p = p->next;
            N++;
        }
        N /= k; //划分N组
        ListNode* new_head =  new ListNode(0);
        ListNode* prev = new_head;
        ListNode* cur = head;
        for(int i = 0; i < N; i++)
        {
            ListNode *first = cur;
            for(int j = 0; j < k; j++)
            {            
                ListNode* next = cur->next;
                cur->next = prev->next;
                prev->next = cur;
                cur = next;
            }
            prev = first;
        }
        //把不需要翻转的接上
        prev->next = cur;
        cur = new_head->next;
        delete new_head;
        return cur;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/424349.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

强化学习_06_pytorch-PPO实践(Hopper-v4)

一、PPO优化 PPO的简介和实践可以看笔者之前的文章 强化学习_06_pytorch-PPO实践(Pendulum-v1) 针对之前的PPO做了主要以下优化&#xff1a; batch_normalize: 在mini_batch 函数中进行adv的normalize, 加速模型对adv的学习policyNet采用beta分布(0~1): 同时增加MaxMinScale …

排序(3)——直接选择排序

目录 直接选择排序 基本思想 整体思路&#xff08;升序&#xff09; 单趟 多趟 代码实现 特性总结 直接选择排序 基本思想 每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待排序的…

JOSEF约瑟 漏电继电器LLJ-400F 配套零序互感器φ100mm 50-500mA 0.1S 导轨安装

系列型号&#xff1a; LLJ-150F(S)漏电继电器 LLJ-160F(S)漏电继电器 LLJ-200F(S)漏电继电器 LLJ-250F(S)漏电继电器 LLJ-300F(S)漏电继电器 LLJ-320F(S)漏电继电器 LLJ-400F(S)漏电继电器 LLJ-500F(S)漏电继电器 LLJ-600F(S)漏电继电器 一、产品用途及特点 LLJ-FS系列漏电继电…

MWC 2024丨美格智能推出5G RedCap系列FWA解决方案,开启5G轻量化新天地

2月27日&#xff0c;在MWC 2024世界移动通信大会上&#xff0c;美格智能正式推出5G RedCap系列FWA解决方案。此系列解决方案具有低功耗、低成本等优势&#xff0c;可以显著降低5G应用复杂度&#xff0c;快速实现5G网络接入&#xff0c;提升FWA部署的经济效益。 RedCap技术带来了…

MATLAB知识点:if条件判断语句的嵌套

​讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自​第4章&#xff1a;MATLAB程序流程控制 我们通过一个…

NCT 全国青少年编程图形化编程(Scratch)等级考试(一级)模拟测试H

202312 青少年软件编程等级考试Scratch一级真题 第 1 题 【 单选题 】 以下说法合理的是( ) A :随意点开不明来源的邮件 B :把密码设置成 abc123 C :在虚拟社区上可以辱骂他人 D :在改编他人的作品前&#xff0c; 先征得他人同意 正确答案&#xff1a; D 试题解析&…

【Scratch画图100例】图49-scratch绘制直角风车 少儿编程 scratch编程画图案例教程 考级比赛画图集训案例

目录 scratch绘制直角风车 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、实现流程 1、案例分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 …

regexpire-攻防世界-MISC

用nc链接靶机&#xff1a; rootkali:~/Desktop# nc 220.249.52.133 37944 Can you match these regexes? Bv*(clementine|sloth)*Q*eO(clinton|alien)*(cat|elephant)(cat|trump)[a-zA-Z]*(dolphin|clementine)\W*(table|apple)* 大致上是服务端给出一个正则表达式&#xff0c…

基于springboot的宠物咖啡馆平台的设计与实现论文

基于Spring Boot的宠物咖啡馆平台的设计与实现 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于Spring Boot的宠物咖啡馆平台的设计与实现的开发全过程。通过分析基于Spring Boot的宠物咖啡馆平台的设计与…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:形状裁剪)

用于对组件进行裁剪、遮罩处理。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 clip clip(value: boolean | CircleAttribute | EllipseAttribute | PathAttribute | RectAttribute) 按指定的形状对当…

数据结构:排序算法+查找算法

一、概念 程序数据结构算法 1.算法的特性和要求 特性&#xff1a; 确定性&#xff08;每次运行相同的输入都是同样的结果&#xff09;、有穷性、输入、输出、可行性 设计要求&#xff1a; 正确性、高效率、低存储、健壮性、可读性 2.时间复杂度 3.常见排序算法的时间复杂…

6.5 共享数据

本节介绍Android的四大组件之一ContentProvider的基本概念和常见用法&#xff1a;首先说明如何使用内容提供器封装内部数据的外部访问接口&#xff0c;然后阐述如何使用内容解析器通过外部接口操作内部数据&#xff0c;最后叙述如何利用内容解析器读写联系人信息&#xff0c;以…

SQL无列名注入

SQL无列名注入 ​ 前段时间&#xff0c;队里某位大佬发了一个关于sql注入无列名的文章&#xff0c;感觉好像很有用&#xff0c;特地研究下。 关于 information_schema 数据库&#xff1a; ​ 对于这一个库&#xff0c;我所知晓的内容并不多&#xff0c;并且之前总结SQL注入的…

2W字-35页PDF谈谈自己对QT某些知识点的理解

2W字-35页PDF谈谈自己对QT某些知识点的理解 前言与总结总体知识点的概况一些笔记的概况笔记阅读清单 前言与总结 最近&#xff0c;也在对自己以前做的项目做一个知识点的梳理&#xff0c;发现可能自己以前更多的是用某个控件&#xff0c;以及看官方手册&#xff0c;但是没有更…

EchoServer回显服务器简单测试

目录 工具介绍 工具使用 测试结果 工具介绍 github的一个开源项目,是一个测压工具 EZLippi/WebBench: Webbench是Radim Kolar在1997年写的一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL&#xff0c;测试网站在压力下工作的…

【Vue3】解锁Vue3黑科技:探索接口、泛型和自定义类型的前端奇迹

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

WebServer -- 注册登录

目录 &#x1f349;整体内容 &#x1f33c;流程图 &#x1f382;载入数据库表 提取用户名和密码 &#x1f6a9;同步线程登录注册 补充解释 代码 &#x1f618;页面跳转 补充解释 代码 &#x1f349;整体内容 概述 TinyWebServer 中&#xff0c;使用数据库连接池实现…

vscode c/c++ 检测到 #include 错误。请更新 includePath。

问题背景 使用vscode打开项目后&#xff0c;头文件显示红色波浪线&#xff0c;没有引入。 检测到 #include 错误。请更新 includePath。已为此翻译单元(xxx)禁用波形曲线。 解决方法 gcc -v -E -x c - 显示所有头文件路径。 打开c_cpp_properties.json文件&#xff0c;粘贴…

Verilog Constructs、Verilog系统任务和功能

下表列出了Verilog构造在Vivado合成中的支持状态。 Verilog系统任务和功能 Vivado合成支持系统任务或功能&#xff0c;如下表所示。Vivado合成会忽略不支持的系统任务。 使用转换函数 使用以下语法对任何表达式调用$signed和$unsigned系统任务。 $signed&#xff08;expr&am…

「爬虫职海录」三镇爬虫

HI&#xff0c;朋友们好 「爬虫职海录」第三期更新啦&#xff01; 本栏目的内容方向会以爬虫相关的“岗位分析”和“职场访谈”为主&#xff0c;方便大家了解一下当下的市场行情。 本栏目持续更新&#xff0c;暂定收集国内主要城市的爬虫岗位相关招聘信息&#xff0c;有求职…