写点什么

算法题学习 --- 链表相加 (二)

作者:桑榆
  • 2022-11-16
    广东
  • 本文字数:2178 字

    阅读完需:约 7 分钟

题目

描述

假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。

给定两个这种链表,请生成代表两个整数相加值的结果链表。

数据范围:0≤n,m≤1000000,链表任意值 0≤val≤9 要求:空间复杂度 O(n),时间复杂度 O(n)

例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为 1->0->0->0。

示例 1

输入:[9,3,7],[6,3]返回值:{1,0,0,0}说明:如题面解释     
复制代码

示例 2

输入:[0],[6,3]返回值:{6,3}
复制代码

备注:

1≤n,m≤1060≤ai,bi≤9

分析

考虑特殊情况

在进行问题分析过程前,我们先考虑一下特殊情况,那么在这道问题中,有哪些情况是特殊的呢?

不难发现,如下情况:

  • head1 为空指针,说明是 0 加另一个数,此时只需要返回另一个头结点就行(head2 为空指针也是相同的情况);

考虑一般情况

  • 链表反转

首先我们可以看到题目中描述的链表中的数据是从高位到低位的,但是我们正常的加法运算都是从低往高位进行计算的,所以我们可以考虑先将链表进行反转,然后再做处理。

  • 加法运算

在我们做加法运算时,可以考虑以哪一个链表作为主链表,基于这样一个原因,两个 n 位数相加,最多会生成一个 n+1 位数,所以我们可以将较长的链表作为主链表,并增加一个 pReturn 节点。

使用两个指针同时访问这两个链表,然后做加法,并进行进位操作,依次操作,最后如果进位还有标志,那就需要增加一个节点保存多余的一位信息。

由于我们使用了较长的链表作为返回信息的主要组成部分,所以在空间上面复杂度可以达到 O(1)

  • 返回信息

前面的计算信息是链表逆序的,这里我们还需要将结果链表再反过来。

如果 pReturn 节点的值为 0,那就返回 pReturn->next;

如果 pReturn 节点的值为 1,那就返回 pReturn.

题解中参考的处理步骤:

  • step 1:任意一个链表为空,返回另一个链表就行了,因为链表为空相当于 0,0 加任何数为 0,包括另一个加数为 0 的情况。

  • step 2:相继反转两个待相加的链表,反转过程可以参考反转链表。

  • step 3:设置返回链表的链表头,设置进位 carry=0.

  • step 4:从头开始遍历两个链表,直到两个链表节点都为空且 carry 也不为 1. 每次取出不为空的链表节点值,为空就设置为 0,将两个数字与 carry 相加,然后查看是否进位,将进位后的结果(对 10 取模)加入新的链表节点,连接在返回链表后面,并继续往后遍历。

注意:这里增加了新的节点,所以空间复杂度是 O(n)的。

  • step 5:返回前将结果链表再反转回来。

代码示例

/** * Definition for singly-linked list. * struct ListNode { *     int val; *     ListNode *next; *     ListNode(int x) : val(x), next(NULL) {} * }; */
class Solution { public: /** * * @param head1 ListNode类 * @param head2 ListNode类 * @return ListNode类 */ ListNode* addInList(ListNode* head1, ListNode* head2) { // write code here if (nullptr == head1) { return head2; } if (nullptr == head2) { return head1; }
// the head point ListNode* pReturn = new ListNode(0); ListNode* pQuick = nullptr; ListNode* pSlow = nullptr; ListNode* pLong = nullptr;
// reverse list int length1 = GetLinkListLength(head1); int length2 = GetLinkListLength(head2); ListNode* pReverse1 = ReverseLinkList(head1); ListNode* pReverse2 = ReverseLinkList(head2); pQuick = pReverse1; pLong = pReverse1; pSlow = pReverse2; if (length2 > length1) { pLong = pReverse2; pQuick = pReverse2; pSlow = pReverse1; }
int entry = 0; ListNode* pPre = nullptr; while (nullptr != pSlow || nullptr != pQuick) { int SlowVal = nullptr == pSlow ? 0 : pSlow->val;
pQuick->val += SlowVal + entry; entry = pQuick->val/10; pQuick->val %= 10;
pPre = pQuick; pQuick = pQuick->next; pSlow = nullptr == pSlow ? nullptr : pSlow->next; } pPre->next = pReturn; pReturn->val = entry;
pReturn = ReverseLinkList(pLong); if (pReturn->val == 1) { return pReturn; } else { return pReturn->next; } }
int GetLinkListLength(ListNode* head) { int length = 0; while (nullptr != head) { length++; head = head->next; } return length; }
ListNode* ReverseLinkList(ListNode* head) { if (nullptr == head || nullptr == head->next) { return head; }
ListNode* pPre = nullptr; ListNode* pCur = head; ListNode* pNext = head->next;
while (nullptr != pCur) { pNext = pCur->next; pCur->next = pPre; pPre = pCur; pCur = pNext; } return pPre; }};
复制代码


发布于: 刚刚阅读数: 4
用户头像

桑榆

关注

北海虽赊,扶摇可接;东隅已逝,桑榆非晚! 2020-02-29 加入

Android手机厂商-相机软件系统工程师 爬山/徒步/Coding

评论

发布
暂无评论
算法题学习---链表相加(二)_算法题_桑榆_InfoQ写作社区