【链表专题】字节真题:单链表相加
本问题对应课程链接:剑指offer刷题第六期
要求:
1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。
2、给出你代码所用的时间复杂度和空间复杂度
代码参考
// 注意,关于链表节点的定义(ListNode),我这里没有给出来哦
class SolutionAdd {
// 反转链表
public ListNode reverseList(ListNode node){
ListNode pre = null;
ListNode q= null;
while (node != null) {
q= node.next;
node.next = pre;
pre = node;
node = q;
}
return pre;
}
// 单链表相加
public ListNode addTwoNumbers(ListNode head1, ListNode head2) {
// 虚拟头节点
ListNode listNode = new ListNode(0);
ListNode p = listNode;
// sum 用来存放进位
int sum = 0;
while (head1 != null || head2 != null || sum!=0) {
if (head1 != null) {
sum += head1.val;
head1 = head1.next;
}
if (head2 != null) {
sum += head2.val;
head2 = head2.next;
}
p.next = new ListNode(sum % 10);
sum = sum / 10;
p = p.next;
}
return listNode.next;
}
}
时间复杂度:O(n+m)
空间复杂度:O(1)
共以下 43 个回答
反转链表 + 字符串相加
代码
时间复杂度:O(max(m, n)),m和n分别是两个链表的长度。
空间复杂度:O(1),需要创建一个新的链表来存储结果。在最坏情况下,当两个链表的长度相等且每一位都产生进位时,结果链表的长度将达到max(m, n),算法本身的空间复杂度是O(1)。
我学习了思路,思路就是将两个链表都反转,然后再进行运算。代码没写
class Solution {
ListNode reverse(ListNode node)
{
ListNode pre=null;
while(node!=null)
{
ListNode temp=node.next;
node.next=pre;
pre=node;
node=temp;
}
return pre;
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode new_l1=reverse(l1);
ListNode new_l2=reverse(l2);
int jinwei=0;
ListNode temp_l1=new_l1;
ListNode temp_l2=new_l2;
ListNode head=new ListNode(-1);
ListNode new_temp=head;
while((temp_l1!=null)&&(temp_l2!=null))
{
int val=(temp_l1.val+temp_l2.val+jinwei)%10;
jinwei=(temp_l1.val+temp_l2.val+jinwei)/10;
new_temp.next=new ListNode(val);
new_temp=new_temp.next;
temp_l1=temp_l1.next;
temp_l2=temp_l2.next;
}
while(temp_l1!=null)
{
int val=(temp_l1.val+jinwei)%10;
jinwei=(temp_l1.val+jinwei)/10;
new_temp.next=new ListNode(val);
new_temp=new_temp.next;
temp_l1=temp_l1.next;
}
while(temp_l2!=null)
{
int val=(temp_l2.val+jinwei)%10;
jinwei=(temp_l2.val+jinwei)/10;
new_temp.next=new ListNode(val);
new_temp=new_temp.next;
temp_l2=temp_l2.next;
}
if(jinwei!=0)
{
new_temp.next=new ListNode(jinwei);
new_temp=new_temp.next;
}
return reverse(head.next);
}
}
先反转链表,然后链表相加,再把新链表反转回来
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pslow = head;
ListNode* pfast = head;
ListNode* pfastn = head;
if (head NULL || head->next NULL) {
return head;
}
pfast = head->next;
pfastn = head->next->next;
while (pfast != NULL) {
if (pslow head) {
pslow->next = NULL;
}
pfast->next = pslow;
pslow = pfast;
pfast = pfastn;
if (pfast NULL) {
break;
}
pfastn = pfastn->next;
}
return pslow;
}
ListNode* listAddition(ListNode* headA, ListNode* headB) {
ListNode* Ar = reverseList(headA);
ListNode* Br = reverseList(headB);
ListNode* Arc = Ar; ListNode* Brc = Br;
ListNode* ll; ListNode* llc;
while (Arc != NULL && Brc != NULL) {
Arc = Arc->next;
Brc = Brc->next;
}
if (Arc != NULL) {
ll = Ar;
}
else if (Brc != NULL) {
ll = Br;
}
else if (Arc NULL && Brc NULL) {
ll = Ar;
}
llc = ll;
int bit = 0;//进位
Arc = Ar; Brc = Br;
while (Arc != NULL && Brc != NULL) {
if ((Arc->val + Brc->val+bit) >= 10) {
ll->val = (Arc->val + Brc->val) – 10+bit;
bit = 1;
}
else {
ll->val = (Arc->val + Brc->val)+bit;
bit = 0;
}
Arc = Arc->next; Brc = Brc->next;
ll = ll->next;
}
ll->val += bit;
return reverseList(llc);
}
};
“`c++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
};
时间O(m+n)
空间O(1)
“`
时间复杂度:O(n)
空间复杂度:O(1)
//单链表相加
//思路:先将两个链表反转,再相加,然后再反转
#include
using namespace std;
struct ListNode{
ListNode head;
int val;
ListNode(int val):val(val){}
};
class solution{
ListNode reverse(ListNode *l){
ListNode *pre, *cur;
pre = NULL, cur = l;
while(cur != NULL){
ListNode * next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
int main(){
}
时间复杂度O(n)
空间复杂度O(n)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head1 = reverse(l1);
ListNode head2 = reverse(l2);
ListNode head = new ListNode(-1);
}
———————————分割线———————————————————
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head1 = reverse(l1);
ListNode head2 = reverse(l2);
ListNode head = new ListNode(-1);
}
时间复杂度:O(m+n)
空间复杂度:O(1)
完整的创建数据结构及实现反转链表与对应位相加的c++代码
#include
#include
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode():val(0),next(nullptr){}
ListNode(int x): val(x),next(nullptr){}
ListNode(int x,ListNode *next):val(x),next(next){}
};
void tailinsert(ListNode *head,int n) //尾插法构建链表 输入头节点及链表长度
{
if(headnullptr)
{
cout<<“head is null”<<endl;
return;
}
ListNode *p=head;
for(int i=0;i<n;i++)
{
ListNode *q=new ListNode;
q->val = i;
q->next=nullptr;
p->next=q;
p=q;
}
}
ListNode * headinsert(ListNode *head,int n) //头插法构建链表 输入头节点及链表长度
{
} a(num);
void printlist(ListNode *head) //打印链表
{
int num = 0;
ListNode *p= head;
while(p!=nullptr)
{
p=p->next;
num++;
}
vector
p =head;
for(int i=0;i<num;i++)
{
a[i] = p->val;
p = p->next;
cout<<a[i]<<endl;
}
}
ListNode *reverseList(ListNode *head) //反转链表
{
if(headnullptr)
{
return head;
}
ListNode *cur=head;
ListNode *pre=nullptr;
ListNode *temp = head->next;
while(cur!=nullptr)
{
cur->next = pre;
pre = cur;
cur = temp;
temp = tempnullptr?nullptr:temp->next;
}
return pre;
}
int addlist(ListNode l1,ListNode *l2) //求链表之和
{
int sum = 0;
ListNode *temp1 = l1;
ListNode *temp2 = l2;
while(temp1!=nullptr&&temp2!=nullptr)
{
sum+=(temp1->val+temp2->val);
temp1 = temp1->next;
temp2 = temp2->next;
}
while(temp1!=nullptr)
{
sum+=temp1->val;
temp1 = temp1->next;
}
while(temp2!=nullptr)
{
sum+=temp2->val;
temp2 = temp2->next;
}
return sum;
}
ListNode *AddList(ListNodel1,ListNode*l2) //两链表合并后的链表
{
int sum =0;
ListNode * result =new ListNode(0);
ListNode *temp = result;
while(l1!=nullptr||l2!=nullptr||sum!=0)
{
if(l1!=nullptr)
{
sum+=l1->val;
l1 = l1->next;
}
if(l2!=nullptr)
{
sum+=l2->val;
l2 = l2->next;
}
ListNode *newnode = new ListNode(sum%10);
temp->next = newnode;
sum = sum/10;
temp = temp->next;
}
return result->next;
}
int main() {
ListNode *l = new ListNode(5);
ListNode *l1 = new ListNode(7);
tailinsert(l,3);
l1 = headinsert(l1,5);
printlist(l);
printlist(l1);
ListNode *reversel = reverseList(l);
ListNode *reversel1 = reverseList(l1);
cout<<“翻转后”<<endl;
printlist(reversel);
printlist(reversel1);
cout<<“链表相加”<<endl;
cout<<addlist(reversel,reversel1)<<endl;;
cout<<“相加后的链表”<<endl;
ListNode *newlist = AddList(reversel,reversel1);
printlist(newlist);
cout<<“最终反转”<<endl;
ListNode *l2 = reverseList(newlist);
printlist(l2);
return 0;
}
思路:
先反转两链表,然后构建一个虚拟节点保存进位,定义sum来存储相加的和 模10来存储进位
时间:O(m+n)
空间:O(1)
class Node():
def init(self, val=0, next=None):
self.val = val
self.next = next
class Solution():
def reverse_list(self,head):
#双指针法
cur,pre = head,None
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
if name “main“:
perf = Solution()
perf.run()
思路:
1.使用双指针法,反转两个链表
2.两个链表相加:当两个链表指向都不为空时候,进行相加;将剩余没加的部分与进位相加得到剩余部分。
先对两个单链表进行反转,然后对反转后的两个链表相加,最后将相加后的结果链表再次反转。
时间复杂度:O(n+m)
空间复杂度:O(1)
也可以用用ArrayDeque
写下思路吧:
先把两个链表反转,从头到尾一次把两个链表节点的值相加,创建新节点,新节点的值为和对10取余,下一个节点的值需要加上前一个节点值对10取整,直到两个链表都为空
思路:链表反转,然后从头到尾依次相加,出现大于10的取余并标记进位,循环到指向两个链表的指针都为空
时间复杂度:O(n)
空间复杂度:O(n)
时间复杂度:O(n)
空间复杂度:O(1)
留坑,后续再学。
class SolutionAdd {
// 反转链表
public ListNode reverseList(ListNode node){
ListNode pre = null;
ListNode q= null;
while (node != null) {
q= node.next;
node.next = pre;
pre = node;
node = q;
}
return pre;
}
// 单链表相加
public ListNode addTwoNumbers(ListNode head1, ListNode head2) {
// 虚拟头节点
ListNode listNode = new ListNode(0);
ListNode p = listNode;
// sum 用来存放进位
int sum = 0;
while (head1 != null || head2 != null || sum!=0) {
if (head1 != null) {
sum += head1.val;
head1 = head1.next;
}
}
打卡
对两个链表进行反转,然后从头相加值,创建链表;遍历两个链表的时候,注意相加值大于10时取余,并相加进位值
时间复杂度O(N)
空间复杂度O(N)
#####第二版:提取公用方法
class Solution:
def reverseList(self, dummy):
head = dummy.next
cur = head; pre = dummy
while cur:
temp = cur.next
cur.next = pre
pre = cur
cur = temp
head.next = None
return pre
def sumList(self, head1, head2):
dummy = ListNode(-1)
p = dummy
cur1 = head1; cur2 = head2
remainder = 0; summ = 0
while cur1 or cur2:
if cur1 and cur2:
summ = cur1.val + cur2.val + remainder
cur1 = cur1.next
cur2 = cur2.next
elif cur1:
summ = cur1.val + remainder
cur1 = cur1.next
elif cur2:
summ = cur2.val + remainder
cur2 = cur2.next
if summ < 10:
remainder = 0
p.next = ListNode(summ)
else:
remainder = 1
p.next = ListNode(summ-10)
p = p.next
if remainder 1:
p.next = ListNode(1)
return dummy.next
def addInList(self , head1: ListNode, head2: ListNode) -> ListNode:
# 先分别反转两个链表,然后对应相加,加完之后再反转回来得到新链表
# 翻转head1
dummy = ListNode(-1)
dummy.next = head1
newHead1 = self.reverseList(dummy)
# 翻转head2
dummy.next = head2
newHead2 = self.reverseList(dummy)
# 求和
newList = self.sumList(newHead1, newHead2)
# 再取反
dummy.next = newList
return self.reverseList(dummy)
第一版:杂乱
class Solution:
def addInList(self , head1: ListNode, head2: ListNode) -> ListNode:
# 先分别反转两个链表,然后对应相加,加完之后再反转回来得到新链表
dummy = ListNode(-1)
dummy.next = head1
cur = head1; pre = dummy
while cur:
temp = cur.next
cur.next = pre
pre = cur
cur = temp
newHead1 = pre
head1.next = None
时间复杂度$O(n)$,空间复杂度$O(n)$
class Solution {
public:
Node* copyRandomList(Node* heada, Node* headb) {
if(!heada) return headb;
if(!headb) return heada;
reverse(heada);
reverse(headb);
Node* head = new Node(0);
Node* tmp = head;
while(!heada && !headb){
tmp->val = heada->val + headb->val;
Node* tmp2 = new Node();
tmp->next = tmp2;
tmp = tmp2;
}
if(heada) tmp->next = head;
if(headb) tmp->next = head;
reverse(head);
return head;
}
Node* reverse(Node* head) {
Node* pre = nullptr;
Node* cur = head;
while(cur){
Node* tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
};
时间复杂度O(N+M),空间复杂度O(1)
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head1 ListNode类
* @param head2 ListNode类
* @return ListNode类
/
ListNodereverseList(ListNodehead){
if(headnullptr)return nullptr;
ListNodepre=nullptr;
ListNode*cur=head;
};
时间复杂度:O(n+m)
空间复杂度:O(n)
时间复杂度:O(n+m)
空间复杂度:O(n+m)
“`c++
#include
using namespace std;
struct Node {
int val;
Node *next;
Node(int val): val(val), next(nullptr) {}
Node(): val(0), next(nullptr) {}
};
Node* reverse(Node* head, int &len) {
len = 0;
if (!head || !head->next) return head;
Node prehead = nullptr;
while (head) {
// cout << head->val << ” “;
len++;
Node tmp = head->next;
head->next = prehead;
prehead = head;
head = tmp;
}
// cout << endl;
return prehead;
}
int add(Node* head1, Node* head2) {
int len1 = 0;
head1 = reverse(head1, len1);
// cout << “len1: ” << len1 << endl;
int len2 = 0;
head2 = reverse(head2, len2);
int maxlen = max(len1, len2);
int sum[maxlen] = {0};
int idx = maxlen – 1;
int c = 0;
while (head1 || head2) {
if (head1) {
c += head1->val;
head1 = head1->next;
}
if (head2) {
c += head2->val;
head2 = head2->next;
}
sum[idx] = c % 10;
idx–;
c /= 10;
}
int res = 0;
for (int i=0; i<maxlen; ++i) {
res = res * 10 + sum[i];
}
return res;
}
int main() {
Node *head = new Node(1);
Node *cur = head;
for (int i=0; i<4; ++i) {
cur->next = new Node(i);
cur = cur->next;
}
Node *head2 = new Node(2);
cur = head2;
for (int i=4; i<9; ++i) {
cur->next = new Node(i);
cur = cur->next;
}
int res = add(head, head2);
cout << “res: ” << res << endl;
res = add(head, nullptr);
cout << “res: ” << res << endl;
return 0;
}
“`
class SolutionAdd {
// 反转链表
public static ListNode reverse(ListNode a) {
ListNode slow = a;
ListNode pre = null;
if(a null) return a;
while (slow != null){
ListNode temp = slow.next;
slow.next = pre;
pre = slow;
slow = temp;
//注意是逆序相加 因此于数给sum,进位给下一位
p.next = new ListNode(sum % 10);
sum = sum / 10;
p = p.next;
}
return listNode.next;
}
}
时间复杂度O(n+m)
空间复杂度 O(1)
// 注意,关于链表节点的定义(ListNode),我这里没有给出来哦
class SolutionAdd {
// 反转链表
public ListNode reverseList(ListNode node){
ListNode pre = null;
ListNode q= null;
while (node != null) {
q= node.next;
node.next = pre;
pre = node;
node = q;
}
return pre;
}
// 单链表相加
public ListNode addTwoNumbers(ListNode head1, ListNode head2) {
// 虚拟头节点
ListNode listNode = new ListNode(0);
ListNode p = listNode;
// sum 用来存放进位
int sum = 0;
while (head1 != null || head2 != null || sum!=0) {
if (head1 != null) {
sum += head1.val;
head1 = head1.next;
}
}
时间复杂度:O(n+m)
空间复杂度:O(1)
public void reverse(ListNode cur, ListNode pre){
if(cur null)return pre;
ListNode res = reverse(cur.next, cur);
cur.next = pre;
return res;
}
时间复杂度O(N)空间复杂度O(1)
class Solution {
private ListNode rev(ListNode head){
if(head null)
return null;
ListNode pre = head;
ListNode cur = head.next;
ListNode temp = cur;
pre.next = null;
while(cur != null){
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
时间复杂度:O(n+m)
空间复杂度:O(n+m)
class SolutionAdd{
public:
ListNode* reverse(ListNode* head) //反转链表
{
if(headnullptr || head->nextnullptr)
{
return head;
}
ListNode* newhead=reverse(head->next);
head->next->next=head;
head->next=nullptr;
return newhead;
}
ListNode* addTwoNumbers(ListNode* head1, ListNode* head2)
{
ListNode* tmphead1=reverse(head1);
ListNode* tmphead2=reverse(head2);
ListNode* dummyhead=new ListNode(0);
ListNode* cur=dummyhead;
int plus=0,sum=0;
while(tmphead1||tmphead2)
{
int num1=tmphead1nullptr?0:tmphead1->val;
int num2=tmphead2nullptr?0:tmphead2->val;
sum=num1+num2+plus;
if(sum>=10)
{
plus=sum/10;
sum=sum%10;
}
cur->next=new ListNode(sum,nullptr);
cur=cur->next;
tmphead1=tmphead1->next;
tmphead2=tmphead2->next;
}
if(plus>0)
{
cur->next=new ListNode(plus);
}
return reverse(dummyhead->next);
}
}
“`
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
// 反转链表
public ListNode reverseList(ListNode head){
ListNode pre = null;
ListNode cur= head;
while (cur != null) {
ne= node.next;
cur.next = pre;
pre = cur;
cur = ne;
}
return pre;
}
}
跟leetcode2类似吧就是要先反转
day3第一题
“`java
public class Solution {
}
思路:
错误:刚开始以为可以直接解决,然后想的是能不能递归,递归最深时候就是最后一个节点,刚好从最后一个节点开始相加,但是两个链表长度可能不一样,不可能让两个链表递归的同时找到对应的相加节点;
正确:先将两个链表进行反转,反转之后,头节点那里就直接是开始相加的位数,然后直接可以将两条链表视为一样长,如果是null的话直接让对应操作数为0,然后相加获得对应位数的值以及进位,进位参与下一个节点的加法中。
最后获得的链表反转之后返回就是结果
思路:1 写一个翻转链表的函数(双指针写的)
2 传入两个头指针,翻转
3 while循环两个链表相加 循环判断条件 h1 || h2 有一个不为空都可进行
4 内部判断 h1指向空 新链表指下一个结点指向l2 h1指向空反之
5 新链表判断 结点/10 后一个结点的值加前结点/10
6 翻转新链表
时间复杂度:O(n + m)
空间复杂度:O(n)
时间复杂度O(N)
空间复杂度O(1)
思路见注释,时间复杂度O(n),n为较长链表,空间复杂度,由于反转链表用了栈,空间复杂度为O(n)
链表常用思路头插法