letcode 2.两数相加(官方题解笔记)

题目描述

给你两个 非空 的链表,表示两个非负的整数。
它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

将两个数相加,并以相同形式返回一个表示和的链表。

除数字 0 之外,这两个数都不会以 0 开头。

1.模拟(加法器)

1.1思路

时间复杂度:O( max(m ,n) )
空间复杂度:O(1)

笔者疑惑:官方给出的程序中,答案链表所占空间大小应为 max(m,n)max(m,n) + 1,所以此处笔者觉得该算法空间复杂度应为 O(max(m,n)),求解惑。

由于输入的两个链表都是逆序存储数字的位数的,因此两个链表中同一位置的数字可以直接相加。

我们同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。
具体而言,如果当前两个链表处相应位置的数字为 n1n2,进位值为 carry,则它们的和为 n1 + n2 +carry
其中,答案链表处相应位置的数字为 (n1 + n2 + carry) mod 10,而新的进位值为 ⌊(n1 + n2 + carry) / 10⌋

如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个 0

此外,如果链表遍历结束后,有 carry > 0,还需要在答案链表的后面附加一个节点,节点的值为 carry

1.2代码

1.C

// 注:前面应该还有定义链表结构体的步骤
// l1:链表1,l2:链表2
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    struct ListNode *head = NULL, *tail = NULL;	// 答案链表的头 [head] 尾 [tail] 结点
    int carry = 0;	// 加法进位
    while (l1 || l2) {	// l1 和 l2 只要有一个没有遍历结束就一直执行此循环
        int n1 = l1 ? l1->val : 0;	// n1 记录 l1 当前结点的数字,若为空则置0,否则置 l1 当前结点的值
        int n2 = l2 ? l2->val : 0;	// n2 记录 l2 当前结点的数字,若为空则置0,否则置 l2 当前结点的值
        int sum = n1 + n2 + carry;	// 相同位置之和 sum = 两链表相同位置的结点的值相加再加上仅为 carry
        // 下面的 if - else 语句用于将对应位置相加的值插入答案链表,因原链表为逆序,故使用尾插法
        if (!head) {	// 头结点为空
            head = tail = malloc(sizeof(struct ListNode));	// 为新结点申请空间
            tail->val = sum % 10;	// 尾插对应目标值
            tail->next = NULL;
        } else {	// 头结点不为空
            tail->next = malloc(sizeof(struct ListNode));	// 为新结点申请空间
            tail->next->val = sum % 10;	// 尾插对应目标值
            tail = tail->next;
            tail->next = NULL;
        }
        carry = sum / 10;	// 计算进位值 carry = ⌊(n1 + n2 + carry) / 10⌋
        if (l1) {	// l1 不为空,遍历 l1 的下一个结点
            l1 = l1->next;
        }
        if (l2) {	// l2 不为空,遍历 l2 的下一个结点
            l2 = l2->next;
        }
    }
    if (carry > 0) {	// 遍历结束后 carry > 0,则额外申请一个新结点存放 carry
        tail->next = malloc(sizeof(struct ListNode));
        tail->next->val = carry;
        tail->next->next = NULL;
    }
    return head;	// 返回答案链表的头结点
}

2.C++

class Solution {
public:
	// 注:前面应该还有定义链表结构体的步骤
	// l1:链表1,l2:链表2
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    	// nullptr 用于避免指针赋空值容易出现的二义性问题,其本质相当于 NULL
        ListNode *head = nullptr, *tail = nullptr;	// 答案链表的头 [head] 尾 [tail] 结点
        int carry = 0;	// 加法进位
        while (l1 || l2) {	// l1 和 l2 只要有一个没有遍历结束就一直执行此循环
            int n1 = l1 ? l1->val: 0;	// n1 记录 l1 当前结点的数字,若为空则置0,否则置 l1 当前结点的值
            int n2 = l2 ? l2->val: 0;	// n2 记录 l2 当前结点的数字,若为空则置0,否则置 l2 当前结点的值
            int sum = n1 + n2 + carry;	// 相同位置之和 sum = 两链表相同位置的结点的值相加再加上仅为 carry
            // 下面的 if - else 语句用于将对应位置相加的值插入答案链表,因原链表为逆序,故使用尾插法
            if (!head) {	// 头结点为空
                head = tail = new ListNode(sum % 10);	// 为新结点申请空间,尾插入对应目标值
            } else {	// 头结点不为空
                tail->next = new ListNode(sum % 10);	// 为新结点申请空间,尾插入对应目标值
                tail = tail->next;
            }
            carry = sum / 10;	// 计算进位值 carry = ⌊(n1 + n2 + carry) / 10⌋
            if (l1) {	// l1 不为空,遍历 l1 的下一个结点
                l1 = l1->next;
            }
            if (l2) {	// l2 不为空,遍历 l2 的下一个结点
                l2 = l2->next;
            }
        }
        if (carry > 0) {	// 遍历结束后 carry > 0,则额外申请一个新结点存放 carry
            tail->next = new ListNode(carry);
        }
        return head;	// 返回答案链表的头结点
    }
};

3.Java

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head = null, tail = null;
        int carry = 0;
        while (l1 != null || l2 != null) {
            int n1 = l1 != null ? l1.val : 0;
            int n2 = l2 != null ? l2.val : 0;
            int sum = n1 + n2 + carry;
            if (head == null) {
                head = tail = new ListNode(sum % 10);
            } else {
                tail.next = new ListNode(sum % 10);
                tail = tail.next;
            }
            carry = sum / 10;
            if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
        }
        if (carry > 0) {
            tail.next = new ListNode(carry);
        }
        return head;
    }
}

4.C#

public class Solution {
    public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head = null, tail = null;
        int carry = 0;
        while (l1 != null || l2 != null) {
            int n1 = l1 != null ? l1.val : 0;
            int n2 = l2 != null ? l2.val : 0;
            int sum = n1 + n2 + carry;
            if (head == null) {
                head = tail = new ListNode(sum % 10);
            } else {
                tail.next = new ListNode(sum % 10);
                tail = tail.next;
            }
            carry = sum / 10;
            if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
        }
        if (carry > 0) {
            tail.next = new ListNode(carry);
        }
        return head;
    }
}

5.Javascript

var addTwoNumbers = function(l1, l2) {
    let head = null, tail = null;
    let carry = 0;
    while (l1 || l2) {
        const n1 = l1 ? l1.val : 0;
        const n2 = l2 ? l2.val : 0;
        const sum = n1 + n2 + carry;
        if (!head) {
            head = tail = new ListNode(sum % 10);
        } else {
            tail.next = new ListNode(sum % 10);
            tail = tail.next;
        }
        carry = Math.floor(sum / 10);
        if (l1) {
            l1 = l1.next;
        }
        if (l2) {
            l2 = l2.next;
        }
    }
    if (carry > 0) {
        tail.next = new ListNode(carry);
    }
    return head;
};

6.Golang

func addTwoNumbers(l1, l2 *ListNode) (head *ListNode) {
    var tail *ListNode
    carry := 0
    for l1 != nil || l2 != nil {
        n1, n2 := 0, 0
        if l1 != nil {
            n1 = l1.Val
            l1 = l1.Next
        }
        if l2 != nil {
            n2 = l2.Val
            l2 = l2.Next
        }
        sum := n1 + n2 + carry
        sum, carry = sum%10, sum/10
        if head == nil {
            head = &ListNode{Val: sum}
            tail = head
        } else {
            tail.Next = &ListNode{Val: sum}
            tail = tail.Next
        }
    }
    if carry > 0 {
        tail.Next = &ListNode{Val: carry}
    }
    return
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值