算法设计与分析 第一周

算法设计与分析 第一周

两数相加


题目描述

算法设计与分析 第一周_第1张图片


选题原因

第一次使用领扣,按照他的题目排列顺序,选择了一道中等难度的题目。由于算法课程还没有很深入,因此没有选择课程相关题目。


题目分析

这道题的难点主要在于使用了链表表示数字,这样做导致三个地方的处理需要十分谨慎:

  • 链表的链接
  • 两数字数位不相等时,较长的数字需要再次加上去
  • 两位数所有位数加完后,是否会产生进位

而由于最高位在链表尾端,反而使得运算变得简单,不需要对齐操作。


解题思路

  • 由一首一尾两个指针指向产生的新数字,每次得出新的一位,就更新尾端,最后返回首指针
  • 计算每一位时,得到结果后取十位作为进位,个位作为结果位
  • 先计算两个数字的共同位数,计算完成后,再计算较长的数字的剩余位,计算完成后,计算进位

问题

计算共同位数部分


  • 野指针问题

在创建新的数字链表过程中,使用了一个指针不停的new并指向next,并且用头节点(头节点为空时)与尾节点(头节点不为空时)指向它。

        struct ListNode* l3;
        int add = 0;
        struct ListNode* t1 = l1;
        struct ListNode* t2 = l2;
        struct ListNode* tail;
        struct ListNode* t3;
        while (t1 -> next != NULL && t2 -> next != NULL) {
            int temp = t1 -> val + t2 -> val + add;
            t3 = new struct ListNode(temp % 10);
            if (l3 == NULL) {
                l3 = t3;
                tail = t3;
            } else {
                tail -> next = t3;
                tail = tail -> next;
            }
            add = temp / 10;
            t1 = t1 -> next;
            t2 = t2 -> next;
            t3 = t3 -> next;
        }

但是在编译的过程中,却出现了这样的错误:
reference binding to misaligned address 0x5f5f7472617473 for type 'const int', which requires 4 byte alignment
出现绑定错误的问题,当 l3 = t3 赋值的时候,无法绑定地址,在查阅资料后,对所有的指针进行了初始化操作,再次编译,结果正常。

        struct ListNode* l3 = NULL;
        int add = 0;
        struct ListNode* t1 = l1;
        struct ListNode* t2 = l2;
        struct ListNode* tail = NULL;
        struct ListNode* t3 = NULL;


  • 共同最高位无法计算

在循环中,判断的条件为 t1 -> next != NULL && t2 -> next != NULL ,但是在实际的操作中,共同的最高位时无法计算的,例如: [1,2,3] + [1,2,3],在计算到 3 时,就已经不在判断条件范围之内了,为了解决这个问题,我在循环结束后,单独进行了一次相同的运算,确保共同最高位能够被计算。

        //计算共同最高位
        {
            int temp = t1 -> val + t2 -> val + add;
            t3 = new struct ListNode(temp % 10);
            if (l3 == NULL) {
                l3 = t3;
                tail = t3;
            } else {
                tail -> next = t3;
                tail = tail -> next;
            }
            add = temp / 10;
            t1 = t1 -> next;
            t2 = t2 -> next;
            t3 = t3 -> next;
        }

不等长数字高位部分


  • 判断是否等长

我使用了新的指针指向了较长的那一个数字剩余部分的最低位,并且以此为判断条件,继续运算:

        //计算剩余位
        {
            struct ListNode* t = NULL;
            if (t1 != NULL) {
                t = t1;
            } 
            if (t2 != NULL){
                t = t2;
            } 
            while (t -> next != NULL) {
                int temp = t -> val + add;
                t3 = new struct ListNode(temp % 10);
                if (l3 == NULL) {
                    l3 = t3;
                    tail = t3;
                } else {
                    tail -> next = t3;
                    tail = tail -> next;
                }
                add = temp / 10;
                t = t -> next;
                t3 = t3 -> next;
            }

在操作中,发现如下报错: Line 59: member access within null pointer of type 'struct ListNode'
当两个数字等长时,则得到的新指针是空的,因此是无法指向下一个next 的,因此,在循环开始之前加上判断的部分: if (t != NULL)

进位部分

进位部分较为简单,没有什么问题。


源代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        struct ListNode* l3 = NULL;
        int add = 0;
        struct ListNode* t1 = l1;
        struct ListNode* t2 = l2;
        struct ListNode* tail = NULL;
        struct ListNode* t3 = NULL;
        while (t1 -> next != NULL && t2 -> next != NULL) {
            int temp = t1 -> val + t2 -> val + add;
            t3 = new struct ListNode(temp % 10);
            if (l3 == NULL) {
                l3 = t3;
                tail = t3;
            } else {
                tail -> next = t3;
                tail = tail -> next;
            }
            add = temp / 10;
            t1 = t1 -> next;
            t2 = t2 -> next;
            t3 = t3 -> next;
        }
        //计算共同最高位
        {
            int temp = t1 -> val + t2 -> val + add;
            t3 = new struct ListNode(temp % 10);
            if (l3 == NULL) {
                l3 = t3;
                tail = t3;
            } else {
                tail -> next = t3;
                tail = tail -> next;
            }
            add = temp / 10;
            t1 = t1 -> next;
            t2 = t2 -> next;
            t3 = t3 -> next;
        }
        //计算剩余位
        {
            struct ListNode* t = NULL;
            if (t1 != NULL) {
                t = t1;
            } 
            if (t2 != NULL){
                t = t2;
            } 
            if (t != NULL) {
                while (t -> next != NULL) {
                    int temp = t -> val + add;
                    t3 = new struct ListNode(temp % 10);
                    if (l3 == NULL) {
                        l3 = t3;
                        tail = t3;
                    } else {
                        tail -> next = t3;
                        tail = tail -> next;
                    }
                    add = temp / 10;
                    t = t -> next;
                    t3 = t3 -> next;
                }
                {
                    int temp = t -> val + add;
                    t3 = new struct ListNode(temp % 10);
                    if (l3 == NULL) {
                        l3 = t3;
                        tail = t3;
                    } else {
                        tail -> next = t3;
                        tail = tail -> next;
                    }
                    add = temp / 10;
                    t = t -> next;
                    t3 = t3 -> next;
                }
            }
        }
        //计算最高位进位
        {
            if (add != 0) {
                t3 = new struct ListNode(add);
                if (l3 == NULL) {
                    l3 = t3;
                    tail = t3;
                } else {
                    tail -> next = t3;
                    tail = tail -> next;
                }
            }
        }
        return l3;
    }
};

运行结果

算法设计与分析 第一周_第2张图片

你可能感兴趣的:(算法分析与设计)