每日一题——两个链表相加

每日一题

两个链表相加

题目链接

在这里插入图片描述

思考历程(错误解法)

  • 看到这题,我首先想到的就是直接正序相加。

  • 首先创建一个新表头,并让其数据域为零。

  • 要进行正序相加,就必须保证两个链表所代表数字的个、十、百·······位对齐,因此我们就必须计算这连个链表的长度,和他们的长度差,再定义两个指针变量cur1、cur2,使其分别指向表一表二的头,最后让链表较长的cur走count个节点,同时将这些节点的数据域链接到新表(需要新建节点)。

  • 当cur1和cur2对齐后,就可以进行逐位相加了,如果相加的值大于等于10,就向前一位进一 。

  • 做到这里,突然就发现不对了。如果我们只需要进一位,如 5 -> 4 -> 9 这种情况,我们只需要定义一个pre保存前一个节点即可,但如果我们要进位多位,如 5 -> 9 -> 9 -> 9 这种情况,显然这种方法是行不通的。

思路

  • 既然正序相加不行,那我们是否可以考虑逆序相加。
  • 单向链表不能从后往前遍历,所以,我们首先应该反转两个单链表(反转单链表的操作)。
  • 反转过后,显然我们可以发现,两个链表所代表数字的个位、十位、百位······都依次对齐,这样我们就可以直接相加,最后将新链表翻转返回即可。

步骤

  • 翻转两个已知链表。
  • 创建新表头,定义指针变量cur1、cur2、cur3,使其分别指向三个链表的头
  • 定义进位标志flag,如果其为1,就需进位,为0则不需进位
  • 在循环中,创建新节点,其数据域为,(cur1->val + cur2->val + flag) % 10,之后再更新flag,flag = (cur1->val + cur2->val + flag) / 10,最后再让cur1,cur2下滑一个节点
  • 只要cur1、cur2、flag有一个不为假,就说明还没有相加完毕,继续循环
  • 最后,返回新表头的next(新表头没有有效数据)

实现代码

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

/**
 * 
 * @param head1 ListNode类 
 * @param head2 ListNode类 
 * @return ListNode类
 */
struct ListNode* FilpLinkList(struct ListNode* phead)      //反转链表
{
    if(!phead)
        return NULL;
	struct ListNode* newHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* cur = phead;
    newHead->next = phead;
    while(cur->next)
    {
        struct ListNode* temp = cur->next;
        cur->next = temp->next;
        temp->next = newHead->next;
        newHead->next = temp;
    }
    return newHead->next;
}
struct ListNode* CreatNewNode(int num)		//创建新节点
{
    struct ListNode* newNode = (struct ListNode *)malloc(sizeof(struct ListNode));
    newNode->next = NULL;
    newNode->val = num;
    return newNode;
}
struct ListNode* addInList(struct ListNode* head1, struct ListNode* head2 ) {
    if(head1 == NULL || head2 == NULL)		//只要head1、head2有一个为空,就相当于加数为0,直接返回不为空的表头,两个都为空,同理。
        return head1 == NULL ? head2 : head1;
    struct ListNode* head3 = (struct ListNode*)malloc(sizeof(struct ListNode));	//新建表头
    //反转链表
    head1 = FilpLinkList(head1);		
    head2 = FilpLinkList(head2);
    struct ListNode* cur1 = head1, *cur2 = head2,*cur3 = head3;
    int flag = 0,val1,val2;
    while(cur1 || cur2 || flag)
    {
        //如果cur为空,说明已经走到表尾,直接令val为0即可
        val1 = cur1 == NULL ? 0 : cur1->val;
        val2 = cur2 == NULL ? 0 : cur2->val;
        cur3->next = CreatNewNode((val1 + val2 + flag) % 10);		//创建新节点
        flag = (val1 + val2 + flag) / 10;		//更新flag
        cur3 =cur3->next;
        //如果cur为空,则停止下滑
        cur1 = cur1 == NULL ? NULL : cur1->next;
        cur2 = cur2 == NULL ? NULL : cur2->next;
    }
    return FilpLinkList(head3->next);	//翻转新表
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Forward♞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值