链表类型题目

news2024/9/30 19:25:48

文章目录

  • 简介
  • 链表的常用技巧
  • 两数相加
    • 原理
    • 代码
    • 代码||
  • 两两交换链表中的节点
    • 代码
    • 原理
  • 重排链表(重要)
    • 原理
    • 代码
  • 合并 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;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LCR 152. 验证二叉搜索树的后序遍历序列

解题思路&#xff1a; 分治 public class Solution {// 验证给定的后序遍历数组是否可以来自一个二叉搜索树(BST)public boolean verifyTreeOrder(int[] postorder) {// 调用递归方法来验证整个postorder数组return verify(postorder, 0, postorder.length - 1);}// 递归方法&…

vue2+若依框架plus交互 路由介绍

本周及寒假 参加了校企合作的工程过程管理&#xff0c;和学长学姐一起写项目&#xff0c;之前学了vue也没有应用&#xff0c;然后对框架很多组件的用法不太了解&#xff0c;前期耽误了一些时间。 框架模块 首先是框架模块的介绍 api存了一些系统管理及发送请求的方法 例如p…

C习题002:澡堂洗澡

问题 输入样例 在这里给出一组输入。例如&#xff1a; 2 5 1 3 3 2 3 3 输出样例 在这里给出相应的输出。例如&#xff1a; No代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB 栈限制 8192 KB 代码 #include<stdio.h> int main() {int N,W,s,t,p;int arr_s[…

Vue+SpringBoot打造大学计算机课程管理平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 实验课程档案模块2.2 实验资源模块2.3 学生实验模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 实验课程档案表3.2.2 实验资源表3.2.3 学生实验表 四、系统展示五、核心代码5.1 一键生成实验5.2 提交实验5.3 批阅实…

Redis安全加固策略:服务账号管理 开启redis密码认证 开启防护模式

Redis安全加固策略&#xff1a;服务账号管理 & 开启redis密码认证 & 开启防护模式 1.1 服务账号管理1.1.1 检测方法1.1.2 加固参考配置操作 1.2 开启redis密码认证1.2.1 检测方法1.2.2 加固参考配置操作 1.3 开启防护模式1.3.1 检测方法1.3.2 加固参考配置操作 &#x…

静态时序分析:SDC约束命令set_case_analysis详解

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 目录 指定值 指定端口/引脚列表 简单使用 set_case_analysis命令用于对电路进行特定模式的设定&#xff0c;例如对于一个工作在正常模式下的芯片&#xff0c;…

Springboot 项目读取yaml的配置文件信息给静态方法使用,以及通过配置 ResourceBundle 类读取config.properties

读取yaml 的配置文件 配置文件信息 iot_saas_tenement:user_id: 7........8d9bprivate_key: MII.......qQbj_url: http://4.....5:8088project_name: iot_s.......rojectdevice_name: te.....ice 创建一个类 ProxyProperties 读取配置文件信息&#xff0c;并对外提供get方法 …

零基础如何快速入门伦敦金交易

伦敦金交易是金融市场中备受关注的一种投资方式。对于想要学习如何炒伦敦金并快速开始交易的人来说&#xff0c;本文将为您提供一份全面而详细的指南。无论您是初学者还是有经验的交易者&#xff0c;本文都将帮助您了解伦敦金交易的基本知识&#xff0c;并提供一些实用的技巧和…

linux环境安装cuda toolkit

1 全新安装 如果环境中没安装过cuda版本&#xff0c; 这种情况下比较简单。 直接在https://developer.nvidia.com/cuda-toolkit-archive选择对应版本下载安装即可。 如下为安装cuda toolkit 11.8. 2 环境中已经存在其他版本 这种情况下比较复杂一些。 首先要确认最高支持的…

Grid-Based Continuous Normal Representation for Anomaly Detection 论文阅读

Grid-Based Continuous Normal Representation for Anomaly Detection 论文阅读 摘要简介方法3.1 Normal Representation3.2 Feature Refinement3.3 Training and Inference 4 实验结果5 总结 文章信息&#xff1a; 原文链接&#xff1a;https://arxiv.org/abs/2402.18293 源码…

06 OpenCV增加图像的对比度

文章目录 理论API代码 理论 图像变换可以看作如下&#xff1a; 像素变换 – 点操作邻域操作 – 区域 调整图像亮度和对比度属于像素变换-点操作 API saturate_cast(value)确保值大小范围为0~255之间Mat.at(y,x)[index]value 给每个像素点每个通道赋值 代码 #include <…

学习:吴恩达:什么是神经元?神经网络如何工作?

学习-吴恩达《AI for everyone》2019 深度学习非技术解释 第2部分 可选.zh_哔哩哔哩_bilibili 深度学习Deep learning 人工神经网络Artificial Neural network 什么是神经网络&#xff1f; 只有一个神经元 4个神经元的神经网络 神经网路的绝妙之处 神经网路的绝妙之处就在…

matplotlib从起点出发(14)_Tutorial_imshow_origin_extent

0 总述 imshow()允许你将图像&#xff08;将进行颜色映射——基于norm和cmap——的2D数组或将按原样使用的3D RGB(A)的数组&#xff09;渲染到数据空间中的矩形区域。最终渲染中图像的方向由原点和范围关键字参数&#xff08;以及生成的AxesImage实例上的属性&#xff09;和Ax…

GVIM常见命令

一、模式之间的切换 二、退出保存 &#xff1a;q 不保存就退出vim &#xff1a;w 保存但不退出vim &#xff1a;wq 保存并退出vim 三、打开侧边栏 如下所示&#xff1a; 在命令模式下输入vt打开侧边栏目录&#xff0c;输入r更新目录 四、光标的移动 不仅是括号&#xff0c;b…

19. 学习人工智能如何从阅读论文中获取一手信息,并推荐一些技术论文

本文为 「茶桁的 AI 秘籍 - BI 篇 第 19 篇」 文章目录 Hi&#xff0c;你好。我是茶桁。 上节课给大家预告了&#xff0c;今天这节课咱们来看一篇论文。我们之前几节课中讲解的内容其实是在一些论文里面有使用到的。 我们先看一下论文的内容&#xff0c;讲讲 ALS。 就像我上节…

力扣34. 在排序数组中查找元素的第一个和最后一个位置(二分查找)

Problem: 34. 在排序数组中查找元素的第一个和最后一个位置 文章目录 题目描述思路复杂度Code 题目描述 思路 Problem: 二分查找常用解题模板&#xff08;带一道leetcode题目&#xff09; 直接套用上述中的寻找左、右边界的二分查找模板即可 复杂度 时间复杂度: O ( l o g n )…

Shellcode ---> 脚本命令入门

今天来浅讲一下shellcode&#xff0c;开始之前&#xff0c;先来乐一乐&#xff0c;哈哈哈哈哈哈哈哈哈哈哈哈 以下的命令你们都别乱用 &#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01…

if-else if-else 语句

if-else if -else语句 定义&#xff1a;是多条件分支语句&#xff0c;即根据多个条件来控制程 序执行的流程。 语法格式&#xff1a; if (表达式) { 若干语句 } else if (表达式) { 若干语句 } … … else { 若干语句 }

云轴科技ZStack与华东师范大学共建产教融合基地

近日&#xff0c;上海云轴信息科技有限公司&#xff08;云轴科技ZStack&#xff09;与华东师范大学上海国际首席技术官学院宣布&#xff0c;共同打造产教融合基地&#xff0c;以促进人才培养与产业需求的全方位融合。这一举措旨在深化教育与产业的合作关系&#xff0c;培养更多…

【Ansys Fluent Web 】全新用户界面支持访问大规模多GPU CFD仿真

基于Web的技术将释放云计算的强大功能&#xff0c;加速CFD仿真&#xff0c;从而减少对硬件资源的依赖。 主要亮点 ✔ 使用Ansys Fluent Web用户界面™&#xff08;UI&#xff09;&#xff0c;用户可通过任何设备与云端运行的仿真进行远程交互 ✔ 该界面通过利用多GPU和云计算功…