『数据结构与算法』LeetCode:2.两数相加!

LeetCode:2.两数相加!

文章目录

    • 1. 题目描述
    • 2. 算法实现
      • 2.1. 解题思路1
      • 2.2. 实现代码1
      • 2.3. 解题思路2
      • 2.4. 实现代码2
    • 3. 参考文章

『数据结构与算法』LeetCode:2.两数相加!_第1张图片

1. 题目描述

  • 给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
  • 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
  • 您可以假设除了数字0之外,这两个数都不会以 0 开头。

示例:

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

2. 算法实现

2.1. 解题思路1

将长度较短的链表在末尾补零使得两个链表长度相等,再一个一个元素对其相加(考虑进位

具体步骤:

  • 获取两个链表所对应的长度
  • 在较短的链表末尾补零
  • 对齐相加考虑进位
『数据结构与算法』LeetCode:2.两数相加!_第2张图片

2.2. 实现代码1

#include <iostream>
#include <vector>
using namespace std;

/* 定义单链表 */
struct ListNode
{
    int val;                                //当前结点的值
    ListNode *next;                         //指向下一个结点的指针
    ListNode(int x) : val(x), next(NULL) {} //初始化当前结点值为x,指针为空
    /*结构体的构造函数,与类的构造函数相同,冒号后面的是初始化列表,也就是给成员val初始化为传入的参数x,next初始化为NULL*/
};

/* 生成单链表 */
ListNode *generateList(vector<int> &arr)
{
    int i = 0;
    ListNode *ln = new ListNode(-1);
    ListNode *list = ln;
    while (i < arr.size())
    {
        ln->next = new ListNode(arr[i]);
        ln = ln->next;
        i++;
    }
    return list->next; //去掉头结点;
}

/* 打印单链表 */
void printList(ListNode *ln)
{
    while (ln != NULL)
    {
        cout << ln->val << "  ";
        ln = ln->next;
    }
    cout << endl;
}

class Solution
{
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
    {
        int len1 = 1; //记录l1的长度
        int len2 = 1; //记录l2的长度
        ListNode *p = l1;
        ListNode *q = l2;
        while (p->next != NULL) //获取l1的长度
        {
            len1++;
            p = p->next;
        }
        while (q->next != NULL) //获取l2的长度
        {
            len2++;
            q = q->next;
        }
        if (len1 > len2) //l1较长,在l2末尾补零
        {
            for (int i = 1; i <= len1 - len2; i++)
            {
                q->next = new ListNode(0);
                q = q->next;
            }
        }
        else
        {
            for (int i = 1; i <= len2 - len1; i++)
            {
                p->next = new ListNode(0);
                p = p->next;
            }
        }
        p = l1;
        q = l2;
        bool count = false;              //记录进位;
        ListNode *l3 = new ListNode(-1); //存放结果的链表
        ListNode *w = l3;                //l3的移动指针
        int i = 0;                       //记录相加结果;
        while (p != NULL && q != NULL)
        {
            i = count + p->val + q->val;
            w->next = new ListNode(i % 10);
            count = i >= 10 ? true : false;
            w = w->next;
            p = p->next;
            q = q->next;
        }
        if (count) //若最后还有进位
        {
            w->next = new ListNode(1);
            w = w->next;
        }
        return l3->next;
    }
};

int main()
{
    vector<int> arr1{2, 4, 3, 1, 5};
    vector<int> arr2{5, 6, 4};
    ListNode *ln1 = generateList(arr1);
    ListNode *ln2 = generateList(arr2);
    printList(ln1);
    printList(ln2);

    Solution sol;
    ListNode *sum = sol.addTwoNumbers(ln1, ln2);
    printList(sum);
    system("pause");
    return 0;
}

运行结果

2  4  3  1  5
5  6  4
7  0  8  1  5
请按任意键继续. . .

2.3. 解题思路2

不对齐补零,若链表不为空则用sum(代表每个位的和的结果)加上,考虑进位。

『数据结构与算法』LeetCode:2.两数相加!_第3张图片

2.4. 实现代码2

#include <iostream>
#include <vector>
using namespace std;

/* 定义单链表 */
struct ListNode
{
    int val;                                //当前结点的值
    ListNode *next;                         //指向下一个结点的指针
    ListNode(int x) : val(x), next(NULL) {} //初始化当前结点值为x,指针为空
    /*结构体的构造函数,与类的构造函数相同,冒号后面的是初始化列表,也就是给成员val初始化为传入的参数x,next初始化为NULL*/
};

/* 生成单链表 */
ListNode *generateList(vector<int> &arr)
{
    int i = 0;
    ListNode *ln = new ListNode(-1);
    ListNode *list = ln;
    while (i < arr.size())
    {
        ln->next = new ListNode(arr[i]);
        ln = ln->next;
        i++;
    }
    return list->next; //去掉头结点;
}

/* 打印单链表 */
void printList(ListNode *ln)
{
    while (ln != NULL)
    {
        cout << ln->val << "  ";
        ln = ln->next;
    }
    cout << endl;
}

/*不对齐补零,若链表不为空则用sum(代表每个位的和的结果)加上,考虑进位。*/
class Solution
{
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
    {
        ListNode *head = new ListNode(-1); //存放结果的链表;
        ListNode *h = head;                //移动指针;
        int sum = 0;                       //每个位的加和结果;
        bool carry = false;                //进位标志;
        while (l1 != NULL || l2 != NULL)
        {
            sum = 0;
            if (l1 != NULL)
            {
                sum += l1->val;
                l1 = l1->next;
            }
            if (l2 != NULL)
            {
                sum += l2->val;
                l2 = l2->next;
            }
            if (carry)
                sum++;
            h->next = new ListNode(sum % 10);
            h = h->next;
            carry = sum >= 10 ? true : false;
        }
        //若最后还有进位
        if (carry)
        {
            h->next = new ListNode(1);
        }
        return head->next;
    }
};

int main()
{
    vector<int> arr1{2, 4, 3};
    vector<int> arr2{5, 6, 4};
    ListNode *ln1 = generateList(arr1);
    ListNode *ln2 = generateList(arr2);
    printList(ln1);
    printList(ln2);

    Solution sol;
    ListNode *sum = sol.addTwoNumbers(ln1, ln2);
    printList(sum);
    system("pause");
    return 0;
}
2  4  3  1  5
5  6  4
7  0  8  1  5
请按任意键继续. . .

3. 参考文章

  • 力扣官方题解:两数相加
  • C++之ListNode

你可能感兴趣的:(数据结构与算法)