《程序员面试金典(第6版)》面试题 02.05. 链表求和(构建一个新链表)

news2024/9/21 16:32:59

题目解析

给定两个用链表表示的整数,每个节点包含一个数位。这些数位是反向存放的,也就是个位排在链表首部。编写函数对这两个整数求和,并用链表形式返回结果。
题目传送门:面试题 02.05. 链表求和

示例:

输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295
输出:2 -> 1 -> 9,即912

示例:

输入:(6 -> 1 -> 7) + (2 -> 9 -> 5),即617 + 295
输出:9 -> 1 -> 2,即912

进阶:

  • 思考一下,假设这些数位是正向存放的,又该如何解决呢?

解题思路与代码

这道题不算一道太难的链表题,主要还是考验了一下你如何构建一条新链表的操作。基本的逻辑也比较简单。你需要去保存一个进位的变量,你需要满十进一。之后就是创建链表的操作啦。

当然你也可以选择去在原链表上去进行操作。但是我觉得那样子指针指的可能会比较乱。我还是选择创建一条新的链表吧。

方案一:遇十进一,创建新链表

就像刚刚说的那样,我们来实现我们的代码:

具体的代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        if(l1 == nullptr) return l2;
        if(l2 == nullptr) return l1;
        int carry = 0;

        ListNode * newList = new ListNode(0);
        ListNode * newHead = newList;

        while(l1 != nullptr && l2 != nullptr){
            int sum = l1->val + l2->val + carry;
            ListNode * temp = new ListNode(sum % 10);
            carry = sum / 10;
            l1 = l1->next;
            l2 = l2->next;
            newHead->next = temp;
            newHead = temp;
        }

        while(l1 != nullptr){
            int sum = carry + l1->val;
            ListNode * temp = new ListNode(sum % 10);
            carry = sum / 10;
            newHead->next = temp;
            newHead = temp;
            l1 = l1->next;
        }

        while(l2 != nullptr){
            int sum = carry + l2->val;
            ListNode * temp = new ListNode(sum % 10);
            carry = sum / 10;
            newHead->next = temp;
            newHead = temp;
            l2 = l2->next;
        }

        if(carry > 0){
            ListNode * temp = new ListNode(carry);
            newHead->next = temp;
        }

        return newList->next;
    }
};

在这里插入图片描述

复杂度分析:

时间复杂度:

  • 我们首先遍历了两个链表,这需要的时间是O(n + m),其中n和m分别代表了两个链表的长度。然后你又分别处理了l1和l2剩余的部分,所以总的时间复杂度为O(n + m),这是线性的时间复杂度。

空间复杂度:

  • 你创建了一个新的链表来存储结果,这需要的空间是O(max(n, m)),因为在最坏的情况下,新链表的长度是最长的输入链表的长度。所以这个代码的空间复杂度是O(max(n, m))。

方案二:优化!使代码看起来更加整洁

根据刚刚写的代码,我发现我不需要那么多的while循环,我只需要一个while循环就行了,整体优化了一下代码结构,使代码看起来更简洁,也更简单。

具体的代码如下:

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode * head = nullptr;
        ListNode * curr = nullptr;
        int carry = 0;
        while(l1 || l2){
            int v1 = l1 ? l1->val : 0;
            int v2 = l2 ? l2->val : 0;
            int sum = v1 + v2 + carry;
            if(!head) head = curr = new ListNode(sum % 10);
            else{
                curr->next = new ListNode(sum % 10);
                curr = curr->next;
            }
            carry = sum / 10;
            if(l1) l1 = l1->next;
            if(l2) l2 = l2->next;
        }
        if(carry) curr->next = new ListNode(carry);
        return head;
    }
};

在这里插入图片描述

复杂度分析

因为只是优化了一下代码结构,所以时间复杂度与空间复杂度完全没有变化。

进阶:思考一下,假设这些数位是正向存放的,又该如何解决呢?

  • 先开个玩笑,其实可以先翻转链表,然后再进行同为相加操作,hh。这种写法我就不写了,没什么必要。

  • 那换一种思路想想,有没有什么数据结构,可以让我们实现先加链表的最后面的节点呢?
    答案是:栈(stack) 。我们可以分别把链表l1,l2的节点分别压入栈中。此时取出来的元素必定是相同位数。如果有的栈先取完了,和刚刚一样,当做0就行。

  • 注意,虽然说,这里的进阶是让你去思考,如果你拿我的代码去leetcode上去提交,题解肯定是不通过的,这是因为,leetcode里面的案例都是个位数是排在前面的,而我们这个进阶思考是让你将最高位排在最前面。

  • 而将最高位排在最前面其实就运用到了一个技巧,就是用循环来插入头节点。也就是反转链表

具体的代码如下:

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        stack<int> s1, s2;
        while (l1) {
            s1.push(l1 -> val);
            l1 = l1 -> next;
        }
        while (l2) {
            s2.push(l2 -> val);
            l2 = l2 -> next;
        }
        int carry = 0;
        ListNode* head = nullptr;
        while (!s1.empty() or !s2.empty() or carry != 0) {
            int a = s1.empty() ? 0 : s1.top();
            int b = s2.empty() ? 0 : s2.top();
            if (!s1.empty()) s1.pop();
            if (!s2.empty()) s2.pop();
            int cur = a + b + carry;
            carry = cur / 10;
            cur %= 10;
            auto pos = new ListNode(cur);
            pos -> next = head;
            head = pos;
        }
        return head;
    }
};

总结

这道题的意义在于以下几点:

  • 链表操作:这道题目考察了对链表的基本操作,包括创建新节点,遍历链表,以及处理链表节点之间的链接关系。

  • 数据结构的选择:在不同的数据表示下,相同的问题可能需要不同的解决策略。例如,这个问题中,数位是反向存放的,这样我们可以直接从链表的头部开始操作,方便处理进位问题。但在进阶问题中,数位是正向存放的,我们就需要将链表反转或者使用栈等数据结构,才能便捷地处理进位问题。

  • 大数运算:这道题目也间接涉及到了大数运算的问题。在实际的编程中,我们可能会遇到超出基本数据类型表示范围的大数,这时候就需要用链表、数组或者字符串等方式来表示这些大数,然后实现基本的数学运算,例如这个问题中的加法运算。

  • 递归与迭代思想:在解决这个问题的时候,我们可以用迭代的方式,也可以用递归的方式。这都考察了我们对这两种基本编程思想的理解。

总的来说,这道题目在帮助我们锻炼基本的链表操作技巧的同时,也提高了我们对数据结构选择,大数运算,以及递归与迭代思想的理解。

最后的最后,如果你觉得我的这篇文章写的不错的话,请给我一个赞与收藏,关注我,我会继续给大家带来更多更优质的干货内容

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

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

相关文章

漏洞管理基础知识

漏洞管理对于端点安全至关重要&#xff0c;是在安全漏洞导致漏洞之前清除安全漏洞的最主动方法之一。 什么是漏洞 漏洞是软件中的错误代码段&#xff0c;会导致软件崩溃或以程序员从未预料到的方式做出响应。黑客可以利用漏洞对计算机系统进行未经授权的访问或对计算机系统执行…

第五十天学习记录:C语言进阶:位段

位段 什么是位段 位段的声明和结构是类似的&#xff0c;有两个不同&#xff1a; 1、位段的成员可以是int,unsigned int或signed int。 2、位段的成员名后边有一个冒号和一个数字。 #define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>//位段-二进制位 struct A {int …

用脚本采集ChatGPT免翻免费镜像

新建了一个网站 ChatGPT人工智能中文站 - ChatGPT人工智能中文站 每天给大家更新可用的国内可用chatGPT免费镜像站 昨天发布了一个教程 本地安装 ChatGPT&#xff01;无需API、 免翻墙、完全免费使用纯正OpenAI的全部功能&#xff01; 支持 Windows、 Mac、NAS、Linux系统 …

led钨丝灯项目笔记

基于ESP-12E的LED钨丝灯作品 原理图&#xff1a; PCB&#xff1a; 嘉立创上面有些封装没有&#xff0c;需要自己画 画完这两个&#xff0c;此时它们还没有相关联&#xff0c;需要将它们关联起来 在封装管理器中将它们关联起来 在这里面就可以找到自己画的封装 如&#xff1a;…

MySQL数据库从入门到精通学习第5天(创建数据表,查看,修改表结构,删除表)

创建数据表&#xff0c;查看&#xff0c;修改表结构 创建数据表查看表结构修改表结构删除表 创建数据表 在对MySQL数据表进行操作之前我们需要创建数据库&#xff0c;并使用USE语句选择数据库。 创建数据库使用CREATE TABLE语句&#xff1a; 语法&#xff1a;CREATE [TEMPOR…

机试打卡 -06 异位词分组(哈希表)

最容易想到的是利用 ord( ) 函数&#xff0c;按照字母计数的特征归类&#xff0c;代码如下&#xff1a; class Solution:def groupAnagrams(self, strs: List[str]) -> List[List[str]]:ans_list[]# 哈希表 {word_count:ans_list中的索引}word_count_dictdict()# 遍历strfo…

NR RLC(三) TM and UM mode

欢迎关注同名微信公众号“modem协议笔记”。 实网下VOLTE通话时常会出现通话无声或者断续的情况&#xff0c;通常的做法是通过检查MO/MT UL发送和DL接收&#xff0c;进一步排查问题原因&#xff0c;modem就避免不了要查看RLC的收发情况&#xff0c;而voice配置一般都是RLC UM …

【Linux系统编程(文件编程)】之读、写文件、文件光标移动

文章目录 一、文件写入二、文件读取三、文件光标移动使用 lseek() 计算文件大小 一、文件写入 write() writes up to count bytes from the buffer starting at buf to the file referred to by the file descriptor fd.write() write() 函数&#xff0c;将从buf缓冲区开始&…

开发实例:Spring Boot、MyBatis和Layui打造增删改查项目

目录导航 1. 技术栈介绍1.1 Springboot1.2 MyBatis1.3 Layui 2. 开发环境2.1 前端示例代码2.2 后端示例代码2.3 数据库建表语句 3. 项目截图4. 运行截图4.1 查询界面4.2 新增界面4.3 修改界面4.4 删除界面 5. 小结6. 完整代码下载 通过学习这个实例项目&#xff0c;我们将积累点…

[HarekazeCTF2019]baby_rop2

小白垃圾笔记&#xff0c;不建议阅读。 这道题学到了两个思想吧&#xff1a; 1.一个是有的函数泄露libc打印不写出来。 2.另一个是printf函数的利用吧。 3.栈对齐好像是只有system有。 分析下题目吧&#xff1a; 64位 绕过nx 本来以为第10行&#xff0c;有坑呢。结果好像是…

简单三招教你音频怎么翻译

随着世界全球化的加速发展和文化交流的增多&#xff0c;音频翻译这项技术变得越来越重要。在国际商务和学术会议中&#xff0c;语言的沟通至关重要。不同国家或地区的参与者会用不同的语言进行交流&#xff0c;这时候&#xff0c;使用音频翻译就可以帮助他们更好地沟通&#xf…

2023年最强测试工程师Linux面试题及答案

前言&#xff1a; 大家好&#xff0c;前段时间有很多朋友给我私信留言&#xff1a;在面试软件测试工作时&#xff0c;部分的liunx的问题答不上来&#xff0c;于是雷叔快马加鞭&#xff0c;连夜给大家整理了一份关于linux的面试题&#xff0c;请看好了。 正文&#xff1a; 1.三…

算法分析基础

问题&#xff1a;如何比较不同算法的性能&#xff1f; 分析算法的运行时间 算法分析的原则 归纳基本操作 如:运算、赋值、比较 统一机器性能 假设基本操作代价均为1 统一机器性能后&#xff0c;算法运行时间依赖于问题输入规模与实例 相同输入规模&#xff0c…

python神经网络实现手写数字识别实验

手写数字识别实验是机器学习中最常见的一个示例&#xff0c;可以有很多种办法实现&#xff0c;最基础的其实就是利用knn算法&#xff0c;根据数字图片对应矩阵与经过训练的数字进行距离计算&#xff0c;最后这个距离最短&#xff0c;那么就认为它是哪个数字。 这里直接通过神经…

项目的延伸

目录 推送模块 1.表 1.1 表字段 1.2 字段类型 1.3 索引 1.4 关联查询 2.参数的含义 3.以技术流的维度讲业务逻辑 4.redis 4.1基础知识 5.设计模式 5.1策略模式 5.2工厂模式 6.遇到的问题 6.1稳定性 7.锁 即时通讯模块 1.表 1.1 表字段 1.2 字段类型 1.3 索…

关于队头阻塞的一些笔记

一、队头阻塞&#xff08;Head-of-Line Blocking&#xff0c;HOL&#xff09; 看到队头&#xff0c;联想到了数据结构课程中学到的队列&#xff0c;队列的一个特点就是FIFO&#xff08;First In First Out&#xff09;&#xff0c;即先进入队列的数据先出队列。所以&#xff0…

【Linux高级 I/O(6)】存储映射 I/O进阶应用(附代码示例)

mprotect()函数 使用系统调用 mprotect()可以更改一个现有映射区的保护要求&#xff0c;其函数原型如下所示&#xff1a; #include <sys/mman.h>int mprotect(void *addr, size_t len, int prot);参数 prot 的取值与 mmap()函数的 prot 参数的一样&#xff0c;m…

Pycharm 配置jupyter notebook 且Windos 安装vim编辑器

请记住要想让你的python成功安装jupyter notebook &#xff0c;你的python最好使用p大于等于python3.7 最好不要在python2大版本中安装jupyternotebook 这个会报错&#xff0c;需要你改一些配置文件&#xff0c;除非你想挑战一下自己&#xff0c;不过后面我会尝试在python2大版…

NeRF-VAE:将场景看作一个分布【ICML‘2021】

文章目录 GQN网络介绍Amortized InferenceNeRF-VAE GQN网络介绍 论文标题&#xff1a;Neural scene representation and rendering 作者&#xff1a;S. M. Ali Eslami, Danilo Jimenez Rezende, et al. 期刊&#xff1a;Science 发表时间&#xff1a;2018/06/15 该文章提出…

单视觉L2市场「鲶鱼」来了,掀起数据反哺高阶新打法

作者 | 张祥威编辑 | 德新 智驾方案的降本行动仍在推进。 早年&#xff0c;单视觉L2市场的玩家以Mobileye、博世为主&#xff0c;后来国内智驾公司加入&#xff0c;共同推动 1V、1R1V、nR1V等不同的方案兴起&#xff0c;L2近乎成为车辆的必备功能。 当下&#xff0c;在行业降低…