Leetcode:Add Two Sum

Problem:Add Two Sum

  You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

  Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
  Output: 7 -> 0 -> 8

Analysis

  这一题属于单链表的题。实现的是单链表的相加,链表的每个元素是1-9的数字,两个数的长度不一定一样长,相加的时候注意进位的问题。

Solutions

  两个链表list1,list2同时遍历,遍历的过程中,将两个链表的数相加,如果这个数小于10,直接赋值给list1中的的val,如果这个数大于10,将这个数取余赋值给list1中的val,再调用add函数,实现进位。最后判断list2的链表是不是还没有走完,如果没有走完,将list2链表的剩余部分给list1.
  空间复杂度:
  

O(1)

  时间复杂度:
  
O(n)

#python code
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
def add(l1):            #发生进位的时候,使用递归调用。
        lisk1 = l1
        while lisk1.val >= 10:
            lisk1.val = lisk1.val % 10
            if lisk1.next == None:
                lisk1.next = ListNode(1)
            else:
                lisk1.next.val += 1
                lisk1.next = add(lisk1.next)
        return l1

class Solution:
    # @param {ListNode} l1
    # @param {ListNode} l2
    # @return {ListNode}
    def addTwoNumbers(self, l1, l2):
        lisk1, lisk2 = l1, l2
        while lisk1 and lisk2:  #当两个链表的next都不为空的时候
            lisk1.val = lisk1.val + lisk2.val
            if lisk1.val >= 10:
                lisk1 = add(lisk1)
            lisk3 = lisk1
            lisk1, lisk2 = lisk1.next, lisk2.next


        while(lisk2):
    #如果l2不为空,l1的链表没有l2的长,将l2的后面链表加在l1的链表的后面
            lisk3.next = lisk2
            print lisk3.next.val
            lisk2 = None

        return l1

其他人的解法方案

//C++ code
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        long num1 = 0, num2 = 0, count = 0, sum = 0;
        vector<int> nums;
        while(l1) {
            num1 = num1 + l1->val*pow(10,count);
            l1 = l1->next;
            count++;
        }
        count = 0;
        while(l2) {
            num2 = num2 + l2->val*pow(10,count);
            l2 = l2->next;
            count++;
        }
        sum = num1 + num2;
        ListNode *ans = new ListNode(sum%10);
        ListNode *cur = ans;
        sum = sum / 10;
        while(sum) {
            cur->next = new ListNode(sum%10);
            cur = cur->next;
            sum /= 10;
        }
        return ans;
    }
};

  将链表表示的数,转换为数字相加,最后再将这个数构建成一个链表。(这个思路我也想到了,只是我没有实施,一直想法用单链表的形式来表示,这个给我一个提醒,以后看到题目的时候,将想到的思路全部写下来,然后在分析哪一个简单、高效、可行)

//C code
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2)   {
    if(NULL == l1 || NULL == l2) {
        return (NULL == l1) ? l2 : l1;
    }

    struct ListNode* result = NULL;
    struct ListNode* head = NULL;

    int sum = 0;
    while(l1 != NULL || l2 != NULL || sum == 1){
        int val = ((l1 == NULL) ? 0 : l1->val) + ((l2 == NULL) ? 0 : l2->val)+sum;
        struct ListNode* tm = (struct ListNode*) malloc(sizeof(struct ListNode));
        tm->next = NULL;
        if(val >= 10){
            tm->val = val % 10;
            sum = 1;
        }else{
            tm->val = val;
            sum = 0;
        }


        if(head == NULL){
            head = tm;
        }else{
            result->next = tm;
        }
        result = tm;

        if(l1 != NULL)l1 = l1->next;
        if(l2 != NULL)l2 = l2->next;
    }
    return head;
}

  遍历单链表,重新构建一个链表用来存放结果。而且这个链表的构建是反着构建的。比我的那个算法好的一个地方,就是使用了进位标志位(这个我也想到了,可是写的时候,没有想清楚,就放弃了),而我进位需要递归,效率上比不上,但是我的算法空间复杂度比这个要低一点(这个节省的有意义吗??)

//Java code
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode curNode = null;
        ListNode prevNode = null;
        ListNode nodeHead= null;

        int carryOver = 0; 
        boolean first = true; // keep track of head of the sumNode chain
        while (l1 !=null || l2 !=null){

            int sum = ((l1!=null)?l1.val:0)+((l2!=null)?l2.val:0)+carryOver; 
            if (l1!=null)
                l1 = l1.next; 
            if (l2!=null)
                l2 = l2.next;
            carryOver = sum /10;
            sum = sum % 10;
            curNode = new ListNode(sum);
            if (first){
                nodeHead = curNode; 
                first = false; 
            }else {
                prevNode.next = curNode; 
            }
            prevNode = curNode; 
        }
        if (carryOver>0){
            prevNode.next = new ListNode(carryOver);
        }
        return nodeHead;
    }

  这一段java代码的设计思想跟上一题差不多,不过可能由于Java效率的问题,时间上要久好多。

summarizes:

这一道题我犯的错误如下:
  错误一:没有意识到进位(题目没有读懂,根据给的例子,应该自己用笔走一遍)
  错误二:算法还没有完全想清楚就开始动手写代码,应该自己在纸上将算法走一遍,然后再来编写代码,这样快一些。
  错误三:发现有例子没有符合算法的时候,使用if-else修补。如果只有几个特殊的点可以,但是如果这个点多了,就不是能够修复的了,这个是原来算法的设计的时候就有很大的问题,这个时候应该回去重新设计算法。
  总结:配合给的例子将题意理解清楚,一定要自己动手走一遍,不能光靠脑子想。想算法的时候,如果在纸上不能走通,那么就不要动手编写代码。

Reference

《Python核心编程》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值