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

news2025/1/11 18:33:44

目录

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

两两交换链表中的节点

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

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

  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.coloradmin.cn/o/1146985.html

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

相关文章

13年测试老鸟,性能压测-死锁定位分析/内存溢出实例(超详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 死锁问题定位与分…

0029Java程序设计-家政服务平台管理系统

文章目录 摘要目录系统设计开发环境 摘要 本文首先研究并介绍国内外目前的背景和现状&#xff0c;在此基础上给出论文的主要研究内容&#xff0c;其次&#xff0c;对家政服务平台管理系统的需求进行了分析。再次&#xff0c;对家政服务平台管理系统进行了总体设计&#xff0c;…

虚拟机安装详细步骤(简单版)

虚拟机作为工作以及学习的工具&#xff0c;是很多人必不可少的一款软件&#xff0c;今天就给大家讲一讲如何将虚拟机成功安装上系统&#xff0c;其中呢也将部分问题在文章中表达&#xff0c;因为很多人表示出现了一些问题&#xff0c;却没有办法解决&#xff0c;所以写了这一篇…

0032Java程序设计-基于JavaEE的智能化酒店点餐收款系统的设计与实现论文

文章目录 摘 要目录系统设计开发环境 摘 要 酒店点餐收款系统是为了实现酒店餐饮自动化管理而设计的&#xff0c;它完全取代了原来酒店餐饮管理一直使用的人工处理的工作方式&#xff0c;并且避免了由于管理人员的工作疏忽以及管理质量问题所造成的各种错误&#xff0c;为及时…

给定两个单链表,编写算法找出两个链表的公共结点

给定两个单链表&#xff0c;编写算法找出两个链表的公共结点 算法思路&#xff1a; 如果两个链表有公共结点&#xff0c;那从某个公共结点开始&#xff0c;就两路并一路了&#xff0c;类似下图 知道这个性质之后我们就可以解决问题了&#xff0c;先判断出两个链表哪个是长链…

【Jenkins】新建任务FAQ

问题1. 源码管理处填入Repository URL&#xff0c;报错&#xff1a;无法连接仓库&#xff1a;Error performing git command: ls-remote -h https://github.com/txy2023/GolangLearning.git HEAD 原因&#xff1a; jenkins全局工具配置里默认没有添加git的路径&#xff0c;如果…

Openssl数据安全传输平台017:客户端在Linux上的编译与调试记录

文章目录 1 在windows上先预编译2 Centos上进入项目文件夹进行编译2.1 找不到protobuf的google文件夹2.2 找不到动态库ljson2.3 动态库软链接失效2.4 undefined reference to Json::Value::asString[abi:cxx11]() const![在这里插入图片描述](https://img-blog.csdnimg.cn/5a8e…

快递单号批量查询教程,掌握包裹动态,让你成为物流达人!

亲爱的读者们&#xff0c;你是否曾经为了追踪快递包裹而烦恼&#xff1f;是否曾经为了查询多个快递单号而感到繁琐&#xff1f;现在&#xff0c;我们为你带来一个高效便捷的解决方案——快递单号批量查询教程&#xff01;让你轻松掌握包裹动态&#xff0c;成为物流达人&#xf…

【深入浅出】寄存器精讲第一期

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、算法模板、汇编语言 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️开篇1.1 &#x1f514;CPU 概述&#xff08;简单了解&#xff09…

两数和的目标 python (初学者vs程序员)

题目描述 1&#xff09;给定一个整数列表&#xff0c;在列表中&#xff0c;从前向后查找两个元素使其相加之和等于目标数&#xff0c;并返回两个整数在列表中的下标。如果没有符合条件的数字&#xff0c;输出False&#xff0c;本题假设题目的解唯一。‬‪‬‪‬‪‬‪‬‮‬‪…

07. 蜂鸣器

07. 蜂鸣器 硬件原理分析代码编写 硬件原理分析 此处为PNP型三极管&#xff0c;BEEP为低的时候三极管才会导通&#xff0c;也就是BEEP0时&#xff0c;蜂鸣器会叫。BEEP是通过SNVS_TAMPER1这个IO控制的 代码编写 将前面的bsp、imx6ul、obj和project拷贝过来 初始化SNVS_TAMPE…

首次cmake 多目录构建失败

新建test3目录&#xff0c;新建如下图空目录&#xff1b;前文有4个源码文件&#xff0c;2个h&#xff0c;2个cpp&#xff1b;把前文的cpp文件拷贝到src目录下&#xff0c;把h文件拷贝到include目录下&#xff1b;前文的CMakeLists.txt拷贝到test3目录下&#xff1b; 在src目录新…

基于小安派AiPi-Eye-S1的Nes游戏机

1.作品展示 作品功能可见以下B站视频 外壳可以使用灰太狼大佬提供的外壳STL文件。在嘉立创三维猴上打印&#xff08;外壳12元快递6元&#xff09;。 外壳从以下的帖子中获取&#xff1a; 模型分享 2.作品说明 2.1 硬件部分 硬件上使用到了AiPi-Eye-S1开发板以及3.5寸 240*3…

社恐了怎么办?如何改变社交恐惧症?

社恐这个词已经算是普及了&#xff0c;自嘲自己是社恐的人真的挺多的&#xff0c;好像一句我社恐了就能解析很多问题&#xff0c;其实真正的社恐远比我们想象的要痛苦多了&#xff0c;社恐能被更多人认识到本来是件好事&#xff0c;但是过于的用社恐来给自己贴标签&#xff0c;…

VBA技术资料MF75:测量所选单元格范围的高度和宽度

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…

从InnoDB索引的数据结构,去理解索引

从InnoDB索引的数据结构&#xff0c;去理解索引 1、InnoDB 中的 BTree1.1、BTree 的组成1.2、BTree中的数据页 2、聚簇索引2.1、聚簇索引的特点2.2、聚簇索引的结构示例2.3、聚簇索引的优缺点 3、非聚簇索引3.1、非聚簇索引结构示例3.2、关于回表3.3、聚簇索引和非聚簇索引的区…

ALS算法在菜品智能推荐系统的应用

核心推荐模块的推荐算法是基于用户推荐模 型&#xff08;user_model&#xff09;协同过滤的矩阵分解过滤算法 ALS。其算法原理可叙述为&#xff1a; ALS收集大数据样本的用户评分喜好信息&#xff0c;训 练推荐模型&#xff0c;基于该模型进行协同过滤。 对于任意一个形如用户-…

记录几个常用的docker镜像

背景 Docker 部署有着非常多的优势&#xff0c;可以帮助提高开发、测试和部署的效率&#xff0c;降低成本&#xff0c;使应用更具可移植性和可扩展性&#xff0c;包括但不限于 标准化应用发布&#xff0c;跨平台和主机使用&#xff1a;Docker的镜像提供了标准化发布环境&…

基于引力搜索算法的无人机航迹规划-附代码

基于引力搜索算法的无人机航迹规划 文章目录 基于引力搜索算法的无人机航迹规划1.引力搜索搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用引力搜索算法来优化无人机航迹规划。 …

报错:Error: error:0308010C:digital envelope routines::unsupported

运行旧项目时&#xff0c;报错&#xff1a;Error: error:0308010C:digital envelope routines::unsupported 主要原因&#xff1a;node版本太高了 解决方法&#xff1a;package.json 包文件中&#xff0c;添加代码 set NODE_OPTIONS--openssl-legacy-provider && &am…