LeetCode:第2题 两数相加 C/C++语言实现

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

思路:将两个链表对应处的值相加即可。需要考虑一个链表为空另一个链表不为空的情况。还需要考虑进位的问题

第一次提交 将各种情况分别考虑,因为当时不知道怎么合并
第二次提交 将各种情况考虑到一起


如果链表中的数字不是按逆序存储的呢?例如:
(3→4→2)+(4→6→5)=8→0→7
看到别人说用递归或栈的思路,但是自己对递归还没有特别熟悉,所以先放下把!以后回来再看


//自己用的是不带头结点链表  

/*
2019.1.17
anan
*/

#include<stdio.h>
#include<malloc.h>
 
struct ListNode {
	int val;
	struct ListNode *next;
};


struct ListNode* createLinkList(int a[], int length);
void dispLinkList(struct ListNode *l);

void dispLinkList(struct ListNode *l){
	struct ListNode *p = l;
	while(p){
		printf("%d ", p->val);
		p = p->next;
	}
	printf("\n");
}

struct ListNode* createLinkList(int a[], int length){
	struct ListNode *s;
    struct ListNode *h=NULL;   //新链表的第一个节点
    struct ListNode *r;  //指向新链表的最后一个节点
	
	for(int i = 0; i < length; i++){
        s = (struct ListNode *)malloc(sizeof(struct ListNode));
        s->val = a[i];
        //printf("s->val:", s->val);
        s->next = NULL;

        if(!h){
            h = s;
            r = h;
        }else{
            r->next = s;
            r = s;
        }		
	}
	
	return h;
}

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode *p = l1;
    struct ListNode *q = l2;
    struct ListNode *h=NULL;   //新链表的第一个节点
    struct ListNode *r;  //指向新链表的最后一个节点
    struct ListNode *s;  //指向新创建的节点
    int carry = 0;

    while(p && q){    // 
        s = (struct ListNode *)malloc(sizeof(struct ListNode));
		s->val = p->val + q->val + carry;        
        carry = 0;
        if(s->val >= 10){
        	carry = 1;
        	s->val = s->val % 10;
		}
        printf("两个都不空  s->val:%d\n", s->val);
        s->next = NULL;
        if(!h){
            h = s;
            r = h;
        }else{
            r->next = s;
            r = s;
        }
        p = p->next;
        q = q->next;
    }

    if(p == NULL){  //p为空 
    	p = q;     
    } 
 	
    while(p){        //p和q中有一个空了,有一个没空 
	    s = (struct ListNode *)malloc(sizeof(struct ListNode));
		s->val = p->val + carry;        
        carry = 0;
        if(s->val >= 10){
        	carry = 1;
        	s->val = s->val % 10;
		}
        printf("一个为空  s->val:%d\n", s->val);
        s->next = NULL;
        if(!h){
            h = s;
            r = h;
        }else{
            r->next = s;
            r = s;
        }
        p = p->next;
    }
    
    //至此,p和q都为空了 
    //此时,如果carry还有值,说明是最后面的进位,要新建一个节点,把这个节点加进去 
    if(carry == 1){     
        s = (struct ListNode *)malloc(sizeof(struct ListNode));
		s->val = carry;        
        carry = 0;
        s->next = NULL;
        if(!h){
            h = s;
            r = h;
        }else{
            r->next = s;
            r = s;
        }
        
    }
    return h;
}

int main(){
//	int a[] = {2,4,3};
//	int b[] = {5,6,4};
//	int length_a = 3;
//	int length_b = 3;
	
//	int a[] = {5};
//	int b[] = {5};
//	int length_a = 1;
//	int length_b = 1;

//	int a[] = {1, 8};
//	int b[] = {0}; 
//	int length_a = 2;
//	int length_b = 1;

	int a[] = {9, 8};
	int b[] = {1}; 
	int length_a = 2;
	int length_b = 1;
	
	struct ListNode* l1;
	struct ListNode* l2;
	struct ListNode* l3;
	
	l1 = createLinkList(a, length_a);
	l2 = createLinkList(b, length_b);
	printf("链表a为:");	
	dispLinkList(l1);
	printf("链表b为:");	
	dispLinkList(l2);
	
	l3 = addTwoNumbers(l1, l2);	
	printf("链表c为:");	
	dispLinkList(l3);
}
//自己用的是不带头结点链表 

#include<stdio.h>
#include<malloc.h>
 
struct ListNode {
	int val;
	struct ListNode *next;
};


struct ListNode* createLinkList(int a[], int length);
void dispLinkList(struct ListNode *l);

void dispLinkList(struct ListNode *l){
	struct ListNode *p = l;
	while(p){
		printf("%d ", p->val);
		p = p->next;
	}
	printf("\n");
}

struct ListNode* createLinkList(int a[], int length){
	struct ListNode *s;
    struct ListNode *h=NULL;   //新链表的第一个节点
    struct ListNode *r;  //指向新链表的最后一个节点
	
	for(int i = 0; i < length; i++){
        s = (struct ListNode *)malloc(sizeof(struct ListNode));
        s->val = a[i];
        //printf("s->val:", s->val);
        s->next = NULL;

        if(!h){
            h = s;
            r = h;
        }else{
            r->next = s;
            r = s;
        }		
	}
	
	return h;
}



struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode *p = l1;
    struct ListNode *q = l2;
    struct ListNode *h=NULL;   //新链表的第一个节点
    struct ListNode *r;  //指向新链表的最后一个节点
    struct ListNode *s;  //指向新创建的节点
    int carry = 0;
    int x;    //放链表1处的值 
	int y;    //放链表2处的值 

	/*
	将p q长度相等和长度不等进行合并处理
	将最后的进位也做合并处理 
	*/ 
    while(p || q || carry){     
        s = (struct ListNode *)malloc(sizeof(struct ListNode));
        x = p ? p->val : 0;
        y = q ? q->val : 0;
		s->val = x + y + carry; 
		
		/*     这段代码可以简化为下面的一段代码  
        carry = 0;
        if(s->val >= 10){
        	carry = 1;
        	s->val = s->val % 10;
		}
		*/
		carry = s->val / 10;
		s->val = s->val % 10; 
        s->next = NULL;
        
        if(!h){
            h = s;
            r = h;
        }else{
            r->next = s;
            r = s;
        }
        
        if(p) p = p->next;
        if(q) q = q->next;
    }
    
    return h;
}

int main(){
//	int a[] = {2,4,3};
//	int b[] = {5,6,4};
//	int length_a = 3;
//	int length_b = 3;
	
//	int a[] = {5};
//	int b[] = {5};
//	int length_a = 1;
//	int length_b = 1;

//	int a[] = {1, 8};
//	int b[] = {0}; 
//	int length_a = 2;
//	int length_b = 1;

//	int a[] = {9, 9};
//	int b[] = {1}; 
//	int length_a = 2;
//	int length_b = 1;

//	int a[] = {0,1};
//	int b[] = {0,1,2};
//	int length_a = 2;
//	int length_b = 3;

	int a[] = {};
	int b[] = {0,1}; 
	int length_a = 0;
	int length_b = 2;
	
	struct ListNode* l1;
	struct ListNode* l2;
	struct ListNode* l3;
	
	l1 = createLinkList(a, length_a);
	l2 = createLinkList(b, length_b);
	printf("链表a为:");	
	dispLinkList(l1);
	printf("链表b为:");	
	dispLinkList(l2);
	
	l3 = addTwoNumbers(l1, l2);	
	printf("链表c为:");	
	dispLinkList(l3);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安安csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值