牛客题解 | 链表相加(二)

news/2025/2/21 10:20:26/文章来源:https://www.cnblogs.com/wc529065/p/18728717

题目

题目链接

题目主要信息:
  • 给定两个链表,每个链表中节点值都是0-9,每个链表就可以表示一个数字
  • 将两个链表表示的数字相加,结果也存在链表中
举一反三:

学习完本题的思路你可以解决如下题目:

BM1.反转链表

BM86.大数加法

方法:反转链表法(推荐使用)

思路:

既然链表每个节点表示数字的每一位,那相加的时候自然可以按照加法法则,从后往前依次相加。但是,链表是没有办法逆序访问的,这是我们要面对第一只拦路虎。解决它也很简单,既然从后往前不行,那从前往后总是可行的吧,将两个链表反转一
下:

while(cur != null){//断开链表,要记录后续一个ListNode temp = cur.next;//当前的next指向前一个cur.next = pre; //前一个更新为当前pre = cur; //当前更新为刚刚记录的后一个cur = temp; 
}

即可得到个十百千……各个数字从前往后的排列,相加结果也是个位在前,怎么办?再次反转,结果不就正常了。

具体做法:

  • step 1:任意一个链表为空,返回另一个链表就行了,因为链表为空相当于0,0加任何数为0,包括另一个加数为0的情况。
  • step 2:相继反转两个待相加的链表,反转过程可以参考反转链表。
  • step 3:设置返回链表的链表头,设置进位carry=0.
  • step 4:从头开始遍历两个链表,直到两个链表节点都为空且carry也不为1. 每次取出不为空的链表节点值,为空就设置为0,将两个数字与carry相加,然后查看是否进位,将进位后的结果(对10取模)加入新的链表节点,连接在返回链表后面,并继续往后遍历。
  • step 5:返回前将结果链表再反转回来。

图示:

alt

Java实现代码:

import java.util.*;
public class Solution {//反转链表public ListNode ReverseList(ListNode pHead) { if(pHead == null)return null;ListNode cur = pHead;ListNode pre = null;while(cur != null){//断开链表,要记录后续一个ListNode temp = cur.next;//当前的next指向前一个cur.next = pre; //前一个更新为当前pre = cur; //当前更新为刚刚记录的后一个cur = temp; }return pre;}public ListNode addInList (ListNode head1, ListNode head2) {//任意一个链表为空,返回另一个if(head1 == null) return head2;if(head2 == null)return head1;//反转两个链表head1 = ReverseList(head1); head2 = ReverseList(head2);//添加表头ListNode res = new ListNode(-1); ListNode head = res;//进位符号int carry = 0; //只要某个链表还有或者进位还有while(head1 != null || head2 != null || carry != 0){ //链表不为空则取其值int val1 = head1 == null ? 0 : head1.val; int val2 = head2 == null ? 0 : head2.val;//相加int temp = val1 + val2 + carry; //获取进位carry = temp / 10; temp %= 10; //添加元素head.next = new ListNode(temp); head = head.next;//移动下一个if(head1 != null) head1 = head1.next;if(head2 != null)head2 = head2.next;}//结果反转回来return ReverseList(res.next); }
}

C++实现代码:

class Solution {
public://反转链表ListNode* ReverseList(ListNode* pHead) { if(pHead == NULL)return NULL;ListNode* cur = pHead;ListNode* pre = NULL;while(cur != NULL){//断开链表,要记录后续一个ListNode* temp = cur->next; //当前的next指向前一个cur->next = pre; //前一个更新为当前pre = cur; //当前更新为刚刚记录的后一个cur = temp; }return pre;}ListNode* addInList(ListNode* head1, ListNode* head2) {//任意一个链表为空,返回另一个if(head1 == NULL) return head2;if(head2 == NULL)return head1;//反转两个链表head1 = ReverseList(head1); head2 = ReverseList(head2);//添加表头ListNode* res = new ListNode(-1); ListNode* head = res;//进位符号int carry = 0; //只要某个链表还有或者进位还有while(head1 != NULL || head2 != NULL || carry != 0){ //链表不为空则取其值int val1 = head1 == NULL ? 0 : head1->val; int val2 = head2 == NULL ? 0 : head2->val;//相加int temp = val1 + val2 + carry; //获取进位carry = temp / 10; temp %= 10; //添加元素head->next = new ListNode(temp); head = head->next;//移动下一个if(head1 != NULL) head1 = head1->next;if(head2 != NULL)head2 = head2->next;}//结果反转回来return ReverseList(res->next); }
};

Python代码实现:

class Solution:#反转链表def ReverseList(self, pHead:ListNode): if pHead == None:return Nonecur = pHeadpre = Nonewhile cur:#断开链表,要记录后续一个temp = cur.next #当前的next指向前一个cur.next = pre #前一个更新为当前pre = cur #当前更新为刚刚记录的后一个cur = temp return predef addInList(self , head1: ListNode, head2: ListNode) -> ListNode:#任意一个链表为空,返回另一个if head1 == None: return head2if head2 == None:return head1#反转两个链表head1 = self.ReverseList(head1) head2 = self.ReverseList(head2)#添加表头res = ListNode(-1) head = res#进位符号carry = 0 #只要某个链表还有或者进位还有while head1 != None or head2 != None or carry != 0: #链表不为空则取其值val1 = 0 if head1 == None else head1.val val2 = 0 if head2 == None else head2.val#相加temp = val1 + val2 + carry #获取进位carry = (int)(temp / 10) temp %= 10#添加元素head.next = ListNode(temp) head = head.next#移动下一个if head1: head1 = head1.nextif head2:head2 = head2.next#结果反转回来return self.ReverseList(res.next) 

复杂度分析:

  • 时间复杂度:\(O(max(m,n))\),其中\(m\)\(n\)分别为两个链表的长度,翻转链表三次,复杂度分别是\(O(n)\)\(O(m)\)\(O(max(m,n))\),相加过程也是遍历较长的链表
  • 空间复杂度:\(O(1)\),常数级指针,没有额外辅助空间,返回的新链表属于必要空间

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客题解 | 顺时针旋转矩阵

牛客输入输出题单题解题目 题目链接 题目主要信息:给定一个\(n*n\)的矩阵,返回其顺时针90度旋转后的结果举一反三: 学习完本题的思路你可以解决如下题目: BM97. 旋转数组 方法:倒置翻转(推荐使用) 知识点:矩阵转置 矩阵转置是将上三角矩阵元素与下三角矩阵元素依据对角线…

牛客题解 | 链表中倒数最后k个结点

牛客输入输出题单题解题目 题目链接 题目的主要信息:一个长度为\(n\)的链表,返回原链表中从倒数第k个节点至尾节点的全部节点 如果该链表长度小于k,请返回一个长度为 0 的链表举一反三: 学习完本题的思路你可以解决如下题目: BM4.合并有序链表 BM5.合并k个已排序的链表 BM…

打造专属任务管理利器:智慧工具私有化部署策略与实践

智慧任务管理工具私有化是指将智慧任务管理工具部署在组织内部的私有服务器或云环境中,以确保数据的安全性、隐私性和完全控制权。以下是对智慧任务管理工具私有化的详细解析: 一、私有化的优势 ● 数据安全:私有化部署确保所有数据存储在组织内部的服务器或私有云中,避免数…

牛客题解 | 设计LFU缓存结构

牛客输入输出题单题解题目 题目链接 题目的主要信息:实现LFU的set与get函数,且复杂度为\(O(1)\) 每次调用这两个函数会给一个频率赋值,超出长度则移除频率最少的,若有频率相同,则移除访问时间最早的举一反三: 学习完本题的思路你可以解决如下题目: BM100. 设计LRU缓存结…

牛客题解 | 设计LRU缓存结构

牛客输入输出题单题解题目 题目链接 题目的主要信息:实现LRU缓存的模拟结构,包括加入函数set,访问函数get 结构有长度限制,加入新数时,超出长度则需要删除最不常访问的,其中set与get都访问 两个函数都是\(O(1)\)举一反三: 学习完本题的思路你可以解决如下题目: BM101. …

牛客题解 | 编辑距离(一)

牛客输入输出题单题解题目 题目链接 题目主要信息:给定两个长度可能不同的字符串,可以对第一个字符串增删改字符 求增删改的最少次数,让第一个字符串变成第二个字符串 字符串中只出现大小写字母举一反三: 学习完本题的思路你可以解决如下题目: BM65 最长公共子序列(二) BM6…

网上学习导航

推荐一个网上学习好玩的地方 学吧导航 网站截图

解决 windows 安装centos7虚拟机 每隔一段时间 虚拟机ip会变动 怎么固定他的ip

查看当前虚拟机的ip地址:我的是192.168.217.136然后获取到网关ip:打开 VMware Workstation,选中你要设置的虚拟机,点击 “编辑” -> “编辑虚拟机设置”。通过ipconfig 可以看到我的是ens160 我的文件就是 ifcfg-ens160 ,然后使用以下命令进行操作sudo nano /etc/sysco…

牛客题解 | 求二叉树的层序遍历

牛客输入输出题单题解题目 题目链接 题目的主要信息:将给定二叉树按行从上到下、从左到右的顺序输出 输出到一个二维数组中,数组中每行就是二叉树的一层举一反三: 学习完本题的思路你可以解决如下题目: BM27. 按之字形顺序打印二叉树 BM35. 判断是否是完全二叉树 方法一:非…

牛客题解 | 没有重复项数字的全排列

牛客输入输出题单题解题目 题目链接 题目主要信息:给定一个数组,求这组数字的全排列 数组无重复元素 以数字在数组中的位置靠前为优先级,按字典序排列输出举一反三: 学习完本题的思路你可以解决如下题目: BM56. 有重复项数字的全排列 BM58. 字符串的排列 BM60. 括号生成 递…

牛客题解 | 最长无重复子数组

牛客输入输出题单题解题目 题目链接 题目主要信息:题目给定一个数组,要找到其中最长的无重复的子数组的长度 子数组必须是数组中连续的一段举一反三: 学习完本题的思路你可以解决如下题目: BM90. 最小覆盖子串 方法:滑动窗口(推荐使用) 知识点1:滑动窗口 滑动窗口是指在数…

牛客题解 | 最长的括号子串

牛客输入输出题单题解题目 题目链接 题目主要信息:一个长度为\(n\)的仅包含左右括号的字符串 计算最长的格式正确的括号子串的长度举一反三: 学习完本题的思路你可以解决如下题目: BM65 最长公共子序列(二) BM66.最长公共子串 BM71.最长上升子序列(一) BM73 最长回文子串 BM…