LeetCode -- Add Two Numbers

来源:互联网 发布:苹果手机越狱软件 编辑:程序博客网 时间:2024/06/03 06:43

题目:
将两个单链表中的数字相加,若某元素和超过10,则右侧元素的值在原来基础上再增加1,以此类推。假设除元素为数字0的单节点链表外,不存在数值为0的多个连续节点开头的链表。


解读:题意在于用单链表的形式模拟多位数的加法操作。存在如下四种情况:

  • 情况1:不存在进位操作,如:[3,2,1]+[3,4,5] = [6,6,6]
  • 情况2:元素个数不对称,如:[3,2]+[3,4,5]
  • 情况3:有进位,在末尾,如:[3,4,6]+[3,1,4]
  • 情况4:元素不对称,有连续进位,在末尾,如[1]+[9,9,9]

方法1:按照上述所列情况,分别包含

  • 优点:方法直接
  • 缺点:效率堪忧
    代码如下
/** * Definition for singly-linked list. * struct ListNode { *     int val; *     struct ListNode *next; * }; */ // 验证链表是否是[0],如果是,则直接返回另一链表bool isZero(struct ListNode* l){    return (l != NULL && l->val==0 && l->next == NULL);}// 首先处理特例,即l1和l2中有一个是[0]这种情况,此时直接返回另一链表    if (isZero(l1) && !isZero(l2)){        return l2;    }else if (!isZero(l1) && isZero(l2)){        return l1;    }    else    {        struct ListNode* temp = l1;        unsigned int carry=0;        // 对于进位在末尾的情况,需要链表的末尾插入操作,此时需要知道其前驱节点。此处首先处理头结点        temp->val += l2->val;        carry = (temp->val > 9)? 1:0;        temp->val = (carry)? (temp->val-10):(temp->val);        // 在循环处理操作中,总是处理当前节点的后继结点,为后续的末尾插入保留指针。        while(temp->next != NULL)        {            if (l2->next != NULL){                temp->next->val += l2->next->val;                l2 = l2->next;            }            // 此处对应的是l1+l2=[3,4,5]+[3,4]这种情形            temp->next->val += carry;            carry =(temp->next->val > 9)? 1:0;            temp->next->val = (carry)? (temp->next->val-10):(temp->next->val);            temp = temp->next;        }        // 此处对应的是l1+l2=[3,4]+[3,4,5]这种情形        while (l2->next != NULL){            temp->next = l2->next;            if (carry){                carry = (l2->next->val > 8)? 1:0;                l2->next->val = (carry)?(l2->next->val-9):(l2->next->val+1);            }            l2 = l2->next;            temp=temp->next;        }        // 此处处理末尾进位的情形,执行链表的尾插法        if (l2->next == NULL){            if (carry){                struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));                node->next = NULL;                node->val = 1;                temp->next=node;            }        }        return l1;    }}

方法2:优化后的非递归算法

从上述分析中可以看出,实际上可以将这几种情形合并成一种情形,减少判断操作。具体操作上,不论输入的链表哪个较长,只要较短的链表达到末尾,就将temp指针指向另一个还未结束的链表,直至两个链表均到达各自的末尾,最后处理尾部进位的情况,即可。代码如下:

方法3:递归操作

尝试性方法

0 0
原创粉丝点击