链表加法与节点交换:数据结构的基础技能

目录

    • 两两交换链表中的节点
    • 单链表加一
    • 链表加法
      • 使用栈实现
      • 使用链表反转实现

两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
在这里插入图片描述

我们依旧使用虚拟头节点来进行交换。
在这里插入图片描述
这张图很是清晰的标明了我们要做的交换步骤:

  1. 首先,创建一个虚拟头节点dummyHead,并将其next指针指向head。然后定义一个临时变量temp,将其初始化为dummyHead。
  2. 使用一个while循环遍历链表,直到遇到链表的末尾(即temp.next或temp.next.next为null)。
  3. 在循环中,首先将temp.next赋值给node1,将temp.next.next赋值给node2。然后将temp的next指针指向node2,将node1的next指针指向node2的next,最后将node2的next指针指向node1,然后把temp指向node1。
  4. 循环结束后,返回dummyHead.next,即交换后的链表的头节点。
 public ListNode swapPairs(ListNode head) {
        ListNode dummyHead = new ListNode(-1);
        dummyHead.next = head;
        ListNode temp = dummyHead;
        while (temp.next != null && temp.next.next != null) {
            ListNode node1 = temp.next;
            ListNode node2 = temp.next.next;
            temp.next = node2;
            node1.next = node2.next;
            node2.next = node1;
            temp = node1;
        }
        return dummyHead.next;
    }

单链表加一

给定一个用单链表表示的整数,然后把这个整数加一。
在这里插入图片描述

public ListNode plusOne(ListNode head) {
        Stack<Integer> stack = new Stack<>();
        while (head != null) {
            stack.push(head.val);
            head = head.next;
        }
        int carry = 0;
        int adder = 1;
        ListNode dummy = new ListNode(0);
        while (!stack.isEmpty() || carry > 0) {
            int digit = stack.isEmpty() ? 0 : stack.pop();
            int sum = digit + carry + adder;
            carry = sum >= 10 ? 1 : 0;
            sum = sum >= 10 ? sum - 10 : sum;
            ListNode node = new ListNode(sum);
            node.next = dummy.next;
            dummy.next = node;
            adder = 0;
        }
        return dummy.next;
    }

我们的实现思路就是先把链表压入栈中,给最低位加一,用carry来记录是否有进位,然后用头插的方式把加一的链表连接起来。

  1. 首先创建一个空的栈(Stack)用于保存链表中的数字,并将链表中的每个节点的值依次入栈。

  2. 创建两个变量carry(进位)和adder(加法器),初始化carry为0, adder为1。

  3. 创建一个虚拟节点dummy,并将其值设置为0。用于存储相加后的链表。

  4. 进入while循环,直到栈为空且没有进位时结束循环。在每次循环中,我们从栈中弹出一个数字digit,并计算和sum = digit + carry + adder。

  5. 判断sum是否大于等于10,如果是,设置carry为1(表示进位),并将sum减去10。否则,carry为0。

  6. 创建一个新的节点node,值为sum,并将node插入到虚拟节点dummy之后。

  7. 继续进行下一次循环之前,将adder设为0,以确保下次循环只进行加法操作。

  8. 返回虚拟节点dummy的下一个节点,即加法操作完成后的链表头节点。

链表加法

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

在这里插入图片描述
我们用两种方式来实现:

使用栈实现

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        Stack<ListNode> stack1 = new Stack<>();
        Stack<ListNode> stack2 = new Stack<>();
        while (l1 != null) {
            stack1.push(l1);
            l1 = l1.next;
        }
        while (l2 != null) {
            stack2.push(l2);
            l2 = l2.next;
        }
        ListNode dummy = new ListNode(-1);
        int carry = 0;
        while (!stack1.isEmpty() || !stack2.isEmpty() || carry != 0) {
            ListNode a = new ListNode(0);
            ListNode b = new ListNode(0);
            if (!stack1.isEmpty()) {
                a.val = stack1.pop().val;
            }
            if (!stack2.isEmpty()) {
                b.val = stack2.pop().val;
            }
            int sum = carry + a.val + b.val;
            int ans = sum % 10;
            carry = sum / 10;
            ListNode cur = new ListNode(ans);
            cur.next = dummy.next;
            dummy.next = cur;
        }
        return dummy.next;
    }

以上代码实现了两个链表的加法操作。

  1. 首先创建两个栈stack1和stack2,分别用于存储链表l1和l2中的节点。

  2. 使用while循环,将链表l1和l2的节点依次入栈到stack1和stack2中。

  3. 创建一个虚拟节点dummy,并将其值设为-1,用于存储相加后的链表。

  4. 创建一个变量carry用于表示进位,初始值为0。

  5. 进入while循环,条件为stack1或stack2不为空,或者carry不为0。在每次循环中,我们从stack1和stack2中弹出当前节点的值。

  6. 创建两个新的节点a和b,并将它们的值设为stack1和stack2弹出的节点值。

  7. 计算和sum = carry + a.val + b.val,以及当前节点的值ans = sum % 10。

  8. 更新进位carry = sum / 10。

  9. 创建一个新的节点cur,将其值设为ans,并将cur插入到虚拟节点dummy之后。

  10. 继续进行下一次循环,直到stack1、stack2为空且carry为0。

  11. 返回虚拟节点dummy的下一个节点,即加法操作完成后的链表头节点。

使用链表反转实现

先将两个链表反转,然后计算结果之后,将结果进行反转。

 public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        l1 = reverse(l1);
        l2 = reverse(l2);
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        int carry = 0;
        while (l1 != null || l2 != null) {
            int val = carry;
            if (l1 != null) {
                val += l1.val;
                l1 = l1.next;
            }
            if (l2 != null) {
                val += l2.val;
                l2 = l2.next;
            }
            cur.next = new ListNode(val % 10);
            carry = val / 10;
            cur = cur.next;
        }
        if (carry > 0) {
            cur.next = new ListNode(carry);
        }
        return reverse(head.next);
    }

    public ListNode reverse(ListNode head) {
        ListNode cur = head;
        ListNode pre = null;
        while (cur != null) {
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }

具体来说:

  1. 首先,将两个输入的链表l1和l2分别进行倒序处理,即反转链表。

  2. 创建一个新的虚拟头节点head,并创建一个指针cur来表示当前节点,初始时指向head

  3. 创建一个变量carry来表示进位,初始值为0。

  4. 进入循环,直到l1和l2都为空为止。在每次循环中,计算当前位的值val,并将carry加上对应位的值。

  5. 如果l1不为空,将l1的值加到val上,并将l1指向下一个节点。

  6. 如果l2不为空,将l2的值加到val上,并将l2指向下一个节点。

  7. 创建一个新的节点newNode,其值为val % 10,并将其插入到新链表中的下一个位置。

  8. 更新carryval / 10

  9. 更新当前节点cur为新插入的节点。

  10. 继续进行下一次循环。

  11. 如果最后还有进位,创建一个值为进位的新节点,并将其插入到新链表末尾。

  12. 将新链表进行反转,返回反转后的头节点。

这样,两个链表的倒序加法操作就完成了。

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

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

相关文章

关于深度学习中Attention的一些简单理解

Attention 机制 Attention应用在了很多最流行的模型中&#xff0c;Transformer、BERT、GPT等等。 Attention就是计算一个加权平均&#xff1b;通过加权平均的权值来自计算每个隐藏层之间的相关度&#xff1b; 示例 Attention 机制 Attention应用在了很多最流行的模型中&am…

基于深度学习的人脸专注度检测计算系统 - opencv python cnn 计算机竞赛

文章目录 1 前言2 相关技术2.1CNN简介2.2 人脸识别算法2.3专注检测原理2.4 OpenCV 3 功能介绍3.1人脸录入功能3.2 人脸识别3.3 人脸专注度检测3.4 识别记录 4 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的人脸专注度…

【机器学习】决策树与分类案例分析

决策树与分类案例分析 文章目录 决策树与分类案例分析1. 认识决策树2. 分类3. 决策树的划分依据4. 决策树API5. 案例&#xff1a;鸢尾花分类6. 决策树可视化7. 总结 1. 认识决策树 决策树思想的来源非常朴素&#xff0c;程序设计中的条件分支结构就是if-else结构&#xff0c;最…

【数据结构】复杂度

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、什么是数据结构二、什么是算法三、算法的效率四、时间复杂度4.1 时间复杂度的概念4…

【100天精通Python】Day72:Python可视化_一文掌握Seaborn库的使用《二》_分类数据可视化,线性模型和参数拟合的可视化,示例+代码

目录 1. 分类数据的可视化 1.1 类别散点图&#xff08;Categorical Scatter Plot&#xff09; 1.2 类别分布图&#xff08;Categorical Distribution Plot&#xff09; 1.3 类别估计图&#xff08;Categorical Estimate Plot&#xff09; 1.4 类别单变量图&#xff08;Cat…

远程IO:实现立体车库高效运营的秘密武器

随着城市的发展&#xff0c;车辆无处停放的问题变得越来越突出。为了解决这个问题&#xff0c;立体车库应运而生。立体车库具有立体空间利用率高、存取车方便、安全可靠等优点&#xff0c;成为现代城市停车的重要解决方案。 立体车库控制系统介绍 在立体车库中&#xff0c;控制…

基于51单片机的四种波形信号发生器仿真设计(仿真+程序源码+设计说明书+讲解视频)

本设计 基于51单片机信号发生器仿真设计 &#xff08;仿真程序源码设计说明书讲解视频&#xff09; 仿真原版本&#xff1a;proteus 7.8 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;S0015 这里写目录标题 基于51单片机信号发生…

简单明了!网关Gateway路由配置filters实现路径重写及对应正则表达式的解析

问题背景&#xff1a; 前端需要发送一个这样的请求&#xff0c;但出现404 首先解析请求的变化&#xff1a; http://www.51xuecheng.cn/api/checkcode/pic 1.请求先打在nginx&#xff0c;www.51xuecheng.cn/api/checkcode/pic部分匹配到了之后会转发给网关进行处理变成localho…

Android底层摸索改BUG(二):Android系统移除预置APP

首先我先提供以下博主博文&#xff0c;对相关知识点可以提供理解、解决、思考的 Android 系统如何预装第三方应用以及常见问题汇集android Android.mk属性说明及预置系统app操作说明系Android 中去除系统原生apk的方法 取消预置APK方法一&#xff1a; 其实就是上面的链接3&a…

Day 4 登录页及路由 (二) -- Vue状态管理

状态管理 之前的实现中&#xff0c;判断登录状态用了伪实现&#xff0c;实际当中&#xff0c;应该是以缓存中的数据为依据来进行的。这就涉及到了应用程序中的状态管理。在Vue中&#xff0c;状态管理之前是Vuex&#xff0c;现在则是推荐使用Pinia&#xff0c;在脚手架项目创建…

linux查看系统版本、内核信息、操作系统类型版本

1. 使用 uname 命令&#xff1a;这将显示完整的内核版本信息&#xff0c;包括内核版本号、主机名、操作系统类型等。 uname -a2. 使用 lsb_release 命令&#xff08;仅适用于支持 LSB&#xff08;Linux Standard Base&#xff09;的发行版&#xff09;&#xff1a;这将显示包含…

HCIE怎么系统性学习?这份HCIE学习路线帮你解决

华为认证体系覆盖ICT行业十一个技术领域共十三个技术方向的认证&#xff0c;今天我们分享的是其中最热门的数据通信方向的HCIE学习路线。 HCIE是华为认证体系中最高级别的ICT技术认证 &#xff0c;旨在打造高含金量的专家级认证&#xff0c;为技术融合背景下的ICT产业提供新的能…

JVS-BI数字大屏设计器:一站式解决方案

数字大屏介绍 数字大屏是当下数据展示、业务监控、指挥调度常见的业务表达形态&#xff0c;常有可视化的图表、效果装饰、事件操作等技术组成酷炫的效果展示。 配置入口 进入JVS-BI&#xff08;bi.bctools.cn&#xff09;&#xff0c;进入大屏页面&#xff0c;如下图所示 ①…

TypeScript之函数以及与JavaScript函数的区别

一、是什么 函数是JavaScript 应用程序的基础&#xff0c;帮助我们实现抽象层、模拟类、信息隐藏和模块 在TypeScript 里&#xff0c;虽然已经支持类、命名空间和模块&#xff0c;但函数仍然是主要定义行为的方式&#xff0c;TypeScript 为 JavaScript 函数添加了额外的功能&…

Docker 部署spring-boot项目(超详细 包括Docker详解、Docker常用指令整理等)

文章目录 DockerDocker的定义Docker有哪些作用Docker有哪些好处使用docker部署springboot项目安装docker创建Dockerfile镜像文件执行镜像文件(Dockerfile文件)查看Docker镜像启动容器查看Docker中运行的容器查看服务容器日志 Docker常用指令查看docker安装目录启动Docker停止Do…

无品牌国产PLC模块调试说明

地址30001对应的aiw9 30002对应aiw10 30003 aiw11 30004 aiw12 模块接线及拨码全部向下&#xff0c;对应的DeviceID为15地址 使用串口线链接的时候a要接b0 b接a0 要反着接才能有数据

金属压铸件自动化3D全尺寸测量设备自动外观检测三维检测-CASAIM

铸造作为现代装备制造工业的基础共性技术之一&#xff0c;铸件产品既是工业制造产品&#xff0c;也是大型机械的重要组成部分&#xff0c;被广泛运用在航空航天、工业船舶、机械电子和交通运输等行业。 铸件形状复杂&#xff0c;一般的三坐标或者卡尺圆规等工具难以获取多特征…

论文阅读——BART

Arxiv: https://arxiv.org/abs/1910.13461 一个去噪自编码器的预训练序列到序列的模型。是一个结合了双向和自回归transformers的模型。 预训练分为两个阶段&#xff1a;任意噪声函数破坏文本和序列模型重建原始文本 一、模型 input&#xff1a;被破坏的文本-->bidirecti…

【开发日记】必须记录一下困扰我两天的问题 MyBatisPlus适配达梦insert时提示:无效的列

【需求】 项目ORM框架使用的是MyBatisPlus&#xff0c;数据库原来使用的是MySQL&#xff0c;现在需要适配达梦。 【问题】 项目ORM框架使用的是MyBatisPlus&#xff0c;数据库原来使用的是MySQL&#xff0c;现在需要适配达梦数据库。 在适配过程中查询、更新、删除都没有问题…
最新文章