LeetCode No.1 两数相加

题目链接

分析

题目考查对链表数据结构的理解,和对加法的操作的理解
链表经常要遍历,所以遍历的框架很重要,接着就是加法的进位了,关键在与进位信号要与每一位相加,若最高位进位信号为1,则新的最高位为1;

实现
#include <stdio.h>
#include <stdlib.h>
struct ListNode
{
    int val;
    struct ListNode *next;
};
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    struct ListNode *Ans,*p,*q,*tmp;
    int c=0;
    Ans=NULL;//初始化
    p=l1;//用来遍历
    q=l2;//同上
    while(1)
    {
        if(p==NULL)//用p存储较长链表的多余部分
        {
            p=q;
            break;
        }
        if(q==NULL)//还是p
        {
            break;
        }
        tmp=(struct ListNode*)malloc(sizeof(struct ListNode));//可以相加,申请一位
        tmp->val=(p->val+q->val+c)%10;//进位信号放里面才合理,例如p->val=4,q->val5,c=1;
        tmp->next=Ans;
        Ans=tmp;
        c=(p->val+q->val+c)/10;//道理同上
        p=p->next;
        q=q->next;
    }
    while(p!=NULL)//较长链表的剩余部分
    {
        tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
        tmp->val=(p->val+c)%10;
        tmp->next=Ans;
        Ans=tmp;
        c=(p->val+c)/10;//其实c在这一过程加一遍就够了,可以改进;
        p=p->next;
    }
    if(c!=0)//最高位是否进位1
    {
        tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
        tmp->val=1;
        tmp->next=Ans;
        Ans=tmp;
        c=0;//这句没什么用;
    }
    p=Ans;//因为结果为头插法,所以就地逆置链表各元素以满足题意
    Ans=NULL;
    while(p!=NULL)
    {
        q=p->next;
        p->next=Ans;
        Ans=p;
        p=q;
    }
    return Ans;
}

void show(struct ListNode* A)//输出链表A
{
    struct ListNode* p=A;
    while(p!=NULL)
    {
        printf("%d\t",p->val);
        p=p->next;
    }
    printf("\n");
}

struct ListNode* getone(int k)//造一个位数为n的链表,可能有bug,按常理出牌应该没问题;
{
    struct ListNode* A=NULL;
    struct ListNode* tmp=NULL;
    int n;
    while(k--)
    {
        scanf("%d",&n);
        tmp=(struct ListNode*)malloc(sizeof(struct ListNode));
        tmp->val=n;
        tmp->next=A;
        A=tmp;
    }
    return A;
};

int main()//测试
{
    struct ListNode *l1,*l2;
    l1=getone(1);
    //show(l1);
    l2=getone(1);
    //show(l2);
    l1=addTwoNumbers(l1,l2);
    show(l1);
    return 0;
}
学习与思考
  1. 链表的就地逆置;
  2. 链表的遍历;
  3. 链表元素的增删查改;
  4. 参考答案中的拓展问:如果链表正序存数字呢?(3→4→2)+(4→6→5)=8→0→7 加数逆置就转换为本题了,结果就是头插的结果;
  5. 代码中还有许多可以改进的地方,希望有想法的朋友留言交流。

猜你喜欢

转载自blog.csdn.net/m0_38062488/article/details/80686702