1. 题目: 链表相加(二)
输入描述:
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
给定两个这种链表,请生成代表两个整数相加值的结果链表。
数据范围:0 \le n,m \le 10000000≤n,m≤1000000,链表任意值 0 \le val \le 90≤val≤9
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
2.算法:
1.暴力算法
2.翻转链表算法
3.算法思想:
暴力算法
//算法思想:先把数字 加到 链表最长的那个链表上 然后利用递归 进位 ,最后传递链表
翻转链表算法
算法思想:
思路:既然链表每个节点表示数字的每一位,那相加的时候自然可以按照加法法则,从后往前依次相加。
但是,链表是没有办法逆序访问的,这是我们要面对第一只拦路虎。
解决它也很简单,既然从后往前不行,那从前往后总是可行的吧,将两个链表反转一 下:
4.代码:
/*************************************************
作者:She001
时间:2022/9/28
题目: 链表相加(二)
描输入描述:
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
给定两个这种链表,请生成代表两个整数相加值的结果链表。
数据范围:0 \le n,m \le 10000000≤n,m≤1000000,链表任意值 0 \le val \le 90≤val≤9
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
***************************************************/
//算法:
//1.暴力算法
// 2.翻转链表算法
#include<bits/stdc++.h>
using namespace std;
typedef struct node
{
int i;
node *next;
};
void print(node * head)//打印链表
{
node* pp= head;//复制头节点
while(pp!=NULL)//判断这个节点是否为空 链表是否结束
{
cout<<pp->i<<" ";
pp=pp->next;//指向下一个
}
cout<<endl;
}
int lianbiao_num(node * head)//函数的作用 返回链表的个数
{
int i=0;
node* pp=head;
while(pp!=NULL)
{
i++;
pp=pp->next;
}
//cout<<"链表中节点的个数: "<<i<<endl;
return i;
}
node * reverseList(node* head)//翻转链表
{
if(head==NULL)
{
return NULL;
}
node * a = head;
node * b = NULL;
while(a!=NULL)
{
node * c = a->next;
a->next=b;
b=a;
a=c;
}
return b;
}
//暴力算法
//算法思想:先把数字 加到 链表最长的那个链表上 然后利用递归 进位 ,最后传递链表
int digui(node * head)//递归的方法, 解决进位的问题
{
if(head==NULL)
{
return 0;
}
int n= head->i + digui(head->next);
int a=n/10;
head->i=n%10;
return a;
}
node * fangfa_1(node * head1,node * head2)//实现的方法
{
if(head1==NULL)//一个链表为空 返回另外一个链表
{
return head2;
}
if(head2==NULL)
{
return head1;
}
node* k1=head1;
node* k2=head2;
int a1= lianbiao_num(k1);
int a2= lianbiao_num(k2);
if(a1>a2)//链表长度的比较
{
for(int i=1;i<=a1-a2;i++)//对齐链表 方便相加
{
k1=k1->next;
}
while(k1!=NULL && k2!= NULL)//对应的位数相加
{
k1->i=(k1->i)+ (k2->i);
k1=k1->next;
k2=k2->next;
}
digui(head1);//进位
return head1;//返回链表
}
else
{
for(int i=1;i<=a2-a1;i++)//对齐链表 方便相加
{
k2=k2->next;
}
while(k1!=NULL && k2!= NULL)//对应的位数相加
{
k2->i=(k1->i)+ (k2->i);
k1=k1->next;
k2=k2->next;
}
digui(head2);//进位
return head2;
}
return NULL;
}
//翻转链表算法
/*
算法思想:
思路:
既然链表每个节点表示数字的每一位,那相加的时候自然可以按照加法法则,从后往前依次相加。
但是,链表是没有办法逆序访问的,这是我们要面对第一只拦路虎。
解决它也很简单,既然从后往前不行,那从前往后总是可行的吧,将两个链表反转一 下:
*/
/*
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7
1 2 4 6 9 1 3 5 6
*/
node * fangfa_2(node * head1,node* head2)
{
if(head1==NULL)
{
return head2;
}
if(head2==NULL)
{
return head1;
}
//翻转两个链表
head1= reverseList(head1);
//print(head1);
head2= reverseList(head2);
//print(head2);
//添加表头 之后翻转答案 就是 结尾 NULL
node *res = new node;
res->i=-1;
node* head=res;
int carry=0;//进位符号
//只有两个链表不为空, 或者 进位的符号不为 0 那么创建一个新的节点,就不会停止
while(head1!=NULL || head2!=NULL || carry!=0)
{
int value1=0;
int value2=0;
//链表不为空 取它的值
if(head1!=NULL)
{
value1=head1->i;
}
if(head2!=NULL)
{
value2=head2->i;
}
//相加
int temp = value1 + value2 +carry;
carry=temp/10;
temp=temp%10;
//添加元素
head->next= new node;
head=head->next;
head->i=temp;
//下一个节点
if(head1!=NULL)
{
head1=head1->next;
}
if(head2!=NULL)
{
head2=head2->next;
}
}
head= reverseList(res->next);
delete res;
return head;
}
int main()
{
//建立 第一个 单链表
node *a1=new node;
node *a2=new node;
node *a3=new node;
node *a4=new node;
node *a5=new node;
node *a6=new node;
node *a7=new node;
node *a8=new node;
node *a9=new node;
a1->i=1;//链表节点的复制
a2->i=2;
a3->i=3;
a4->i=4;
a5->i=5;
a6->i=6;
a7->i=7;
a8->i=8;
a9->i=9;
a1->next=a2;//链表的连接
a2->next=a3;
a3->next=a4;
a4->next=a5;
a5->next=a6;
a6->next=a7;
a7->next=a8;
a8->next=a9;//a5 是 两个链表的节点
a9->next=NULL;
//建立 第二个 单链表
node *b1=new node;
node *b2=new node;
node *b3=new node;
node *b4=new node;
node *b5=new node;
node *b6=new node;
node *b7=new node;
b1->i=1;//链表节点的复制
b2->i=2;
b3->i=3;
b4->i=4;
b5->i=5;
b6->i=6;
b7->i=7;
b1->next=b2;//链表的连接
b2->next=b3;
b3->next=b4;
b4->next=b5;
b5->next=b6;
b6->next=b7;
b7->next=NULL;
node *k1 =fangfa_1(a1,b1);
print(k1);
//node *k =fangfa_2(a1,b1);
//print(k);
return 0;
}