题目连接:
链表相加(二)_牛客题霸_牛客网 (nowcoder.com)
题目描述:
描述
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
给定两个这种链表,请生成代表两个整数相加值的结果链表。
数据范围: 0≤n,m≤1000000,链表任意值 0≤val≤9
要求:空间复杂度 O(n),时间复杂度 O(n)
例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为 1->0->0->0。
题目解法:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
*BM11 链表相加(二)
描述
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
给定两个这种链表,请生成代表两个整数相加值的结果链表。
数据范围:0≤n,m≤1000000,链表任意值 0≤val≤9
要求:空间复杂度 O(n),时间复杂度 O(n)
例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为 1->0->0->0。
9 - 3 - 7
+ 6 - 3
--------------
1 - 0 - 0 - 0
*/
/**************************code*****************************************/
struct ListNode {
int val;
struct ListNode *next;
};
struct ListNode* addInList(struct ListNode* head1, struct ListNode* head2 ) {
// write code here
struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
dummyHead->val = 0;
int List1Count = 0, List2Count = 0;
struct ListNode* tmp, *longList, *shortList;
int ov = 0; //overflow 进位标志
/* 模拟栈:先入后出 */
int st1_i = -1, st2_i = -1, st_i, st_i_tmp;
// int st1[15]={0}, st2[15]={0}, st[15]={0}; // 本地调试用
int *st1, *st2, *st; //st1是较长的链表的栈,st2是较短的链表的栈,st是相加后存储的栈,st需要比st1大,防止相加后进位
tmp = head1; //获得head1的长度
while(tmp){
tmp = tmp->next;
List1Count++;
}
tmp = head2; //获得head2的长度
while(tmp){
tmp = tmp->next;
List2Count++;
}
//根据head1 head2的长度,分别给st1\st2\st申请空间
st1 = (int*)malloc(sizeof(int)*(List1Count >= List2Count ? (List1Count+1) : (List2Count+1)));
st2 = (int*)malloc(sizeof(int)*(List1Count >= List2Count ? (List2Count+1) : (List1Count+1)));
st = (int*)malloc(sizeof(int)*(List1Count >= List2Count ? (List1Count+2) : (List2Count+2)));
if(List1Count >= List2Count){ //根据长度,将head1、2用longList shortList来装,方便后面操作
longList = head1;
shortList = head2;
}else{
longList = head2;
shortList = head1;
}
tmp = longList; //将长链表的值一个个入栈
while(tmp){
st1[++st1_i] = tmp->val;
tmp = tmp->next;
}
printf("\r\nst1: "); //打印st1,查看是否正确
for(int i=0;i<st1_i;i++)printf("%d",st1[i]);
tmp = shortList; //将短链表的值一个个入栈
while(tmp){
st2[++st2_i] = tmp->val;
tmp = tmp->next;
}
printf("\r\nst2: ");
for(int i=0;i<st2_i;i++)printf("%d",st2[i]);
st_i = st1_i+1; //长链表st1的索引加一,赋值为结果栈st的索引,加一是为了防止进位
st_i_tmp = st_i;
dummyHead->next = longList; //将虚拟头节点的下一个指向长链表,虚拟头节点可用来装进位
while(st1_i >= 0 || st2_i >= 0 || ov){ //判断栈st1 st2 是否空,ov进位标志是否存在
if(st1_i >= 0 && st2_i >= 0){ //1、当st1 st2均不为空
if(st1[st1_i] + st2[st2_i] + ov > 9){ //栈顶值相加并加上进位标志,大于9表示溢出,有进位
st[st_i_tmp] = st1[st1_i] + st2[st2_i] + ov - 10;
ov = 1; //赋值ov
}else{ //没有进位溢出,ov置0
st[st_i_tmp] = st1[st1_i] + st2[st2_i] + ov;
ov = 0;
}
}else if(st1_i >= 0 && st2_i < 0){//2、当st2为空,因为st1是长链表的栈,因此总是st2先空
if(st1[st1_i] + ov > 9){
st[st_i_tmp] = st1[st1_i] + ov - 10;
ov = 1;
}else{
st[st_i_tmp] = st1[st1_i] + ov;
ov = 0;
}
}else if(st1_i < 0 && st2_i < 0){ //3、当st1 st2均为空,此时还能进入循环说明有ov,因此将st当前位设为ov(也就是1)
st[st_i_tmp] = ov;
ov = 0;
}
st1_i--, st2_i--, st_i_tmp--; //栈索引-1
}
tmp = dummyHead; //将st结果栈的值一个个赋值为链表(dummyHead->longList)
for(int i=0; i<=st_i; i++){
tmp->val = st[i];
tmp = tmp->next;
}
tmp = NULL; //末尾置NULL
if(st[0] == 1) //根据st结果栈的元素进行判断,是否有进位导致链表延长1,
return dummyHead; //有延长就返回赋值好的虚拟头节点dummyHead
else
return dummyHead->next; //没有进位则返回dummyHead->next,即longList
}
/**************************end******************************************/
void buildList(struct ListNode* head, int * input, int n){
for(int i=0; i<n; i++){
head->next = (struct ListNode*)malloc(sizeof(struct ListNode));
head->val = input[i];
head = head->next;
head->next = NULL;
head->val = 0;
}
}
int main ()
{
// int input1[]={4,6,0,2,6,6,3,6,3,0,7,8,0,4,1,7,0,5,6,5,2,4,9,9,1,5,1,5};
// int input2[]={6,2,7,8,6,4,7,0,9,3,0,3,6,2,5,6,0,9,6,2,7,4,2,7,1,0,9,0,5,6,5,4,9,1,8,9,3,4,0,2,1,8,8,2,2,0};
int input1[]={5,9,7,5,7,1,2,6,4,2,7,8,9,6,1,6,6,1,1,4,2,9,5,5,0,4,6,3,0,4,3,5,6,7,0,5,5,4,4,0};
int input2[]={1,3,2,5,0,6,0,2,1,4,3,9,3,0,9,9,0,3,1,6,5,7,8,6,2,3,8,5,0,9,7,9,4,5,9,9,4,9,3,6};
struct ListNode LNa, LNb;
buildList(&LNa, input1, sizeof(input1)/sizeof(int));
buildList(&LNb, input2, sizeof(input2)/sizeof(int));
struct ListNode* ret = addInList(&LNa, &LNb);
printf("\r\nret:");
while(ret){
printf("%d", ret->val);
ret = ret->next;
}
return 0;
}