牛客-c语言刷题- 链表相加(二)

题目连接:

链表相加(二)_牛客题霸_牛客网 (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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值