LeetCode Problem 2解析

  Problem 2考察的是链表问题,两条链表,对应节点的值相加并放入新链表对应的节点中,然后利用值-10判断产生进位,然后将进位参与到下一节点的运算中,最后直到两条链表的节点为空并且不在进位。
  由于是两条链表,因此必须考虑一长一短,在短的链表的节点处理完后,仅需处理长链表的剩余节点以及carry,此外还要考虑进位产生一个尾节点的情况,如[1],[9,9]相加后的链表长度为三,而最后一个节点是carry的值,因此,程序的时间复杂度为O(max(l1.length,l2.length))相当于遍历最长链表的时间复杂度。
  因此代码如下

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    int carry = 0;
    struct ListNode *l3, *point;
    l3 = point = NULL;
    while(l1 || l2 || carry) {
        /*
        当l1,l2或进位仍有结点未加或有值时对l3链表扩容一个结点,头结点为空时先创建头结点。
        */
        if(!l3) {
            l3 = point = (struct ListNode*)malloc(sizeof(struct ListNode));
            l3->next = NULL;
        } else {
            point->next = (struct ListNode*)malloc(sizeof(struct ListNode));
            point = point->next;
            point->next = NULL;
        }
        /*
        四种情况下的结点相加(1)l1l2相加的结点都存在,(2)l1结点存在,(3)l2结点存在,(4)l1l2结点都不存在
        */
        if(l1 && l2) {
            point->val = l1->val + l2->val + carry;
            l1 = l1->next;
            l2 = l2->next;
        } else if(l1) {
            point->val = l1->val + carry;
            l1 = l1->next;
        } else if(l2) {
            point->val = l2->val + carry;
            l2 = l2->next;
        } else {
            point->val = carry;
        }
        /*
        判断新链表上的结点值是否大于10,大于10的进位并减去10,否则不进位
        */
        if(point->val >= 10) {
            carry = 1;
            point->val = point->val - 10;
        } else {
            carry = 0;
        }
    }
    return l3;
}

  AC后,我看了一下他的代码,设计的思路和我的想法差不多,但代码比我的代码简洁了不少,我用C将他的方法重写了一下

struct ListNode* addTwoNumbers2(struct ListNode* l1, struct ListNode* l2) {
    int x, y, sum, carry = 0;
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* current = head;
    while(l1||l2) {
        if(l1) {
            x = l1->val;
        } else {
            x = 0;
        }
        if(l2) {
            y = l2->val;
        } else {
            y = 0;
        }
        sum = x + y + carry;
        carry = sum / 10;
        current->next = (struct ListNode*)malloc(sizeof(struct ListNode));
        current->next->val = sum % 10;
        current = current->next;
        if(l1) {
            l1 = l1->next;
        }
        if(l2) {
            l2 = l2->next;
        }
    }
    if (carry > 0) {
        current->next = (struct ListNode*)malloc(sizeof(struct ListNode));
        current = current->next;
        current->val = carry;
    }
    current->next = NULL;
    return head->next;
}

  由于他的原来的写法是JAVA,所以新建链表结点比C方便,此外源代码中的判断都用三目运算符?:替代了,所以会更简洁,但我觉得这样会影响代码的维护性,所以仍然用了if判断。从上面代码可知,他的策略是将头结点置空来减少while里的新建头结点的代码量,同时也便于链表的读取和维护。此外他利用判断结点是否为空来决定后面表达式sum = x + y + carry中x, y的值,这样增加了程序的可读性,避免了被if,else if绕晕,这点值得我借鉴。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值