侧边栏壁纸
  • 累计撰写 106 篇文章
  • 累计创建 3 个标签
  • 累计收到 19 条评论
标签搜索

目 录CONTENT

文章目录

LeetCode刷题笔记-2.两数相加

卑微幻想家
2022-01-11 / 0 评论 / 0 点赞 / 204 阅读 / 2,333 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-03-24,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

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

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

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

实例1:

img

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:

  • 每个链表中的节点数在范围 [1, 100] 内
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

辅助方法

在解这道题的之前我先写了两个方法,一个是将int数组,转换成ListNode对象,第二个是ListNode的toString方法,用来友好的输出ListNode对象。

/**
 * 将int数组转换为ListNode对象
 */
public static ListNode intArrayConvertNode(int[] arrays) {
    ListNode head = null;
    ListNode tail = null;
    for (int val : arrays) {
        ListNode node = new ListNode(val);
        if (head == null) {
            head = node;
        } else {
            tail.next = node;
        }
        tail = node;
    }
    return head;
}

定义一个head和tail两个对象,分别用来代表链表的头节点和尾结点。开始时head和tail都为空,开始第一个转换时head为null,这时head和tail都指向新节点node,以后每次添加节点,都是在tail的后面添加即:tail.next = node,然后再将tail置为新的尾部即:tail = node。head始终指向第一个节点。

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    ListNode next = this;
    while (next != null) {
        builder.append(next.val);
        next = next.next;
        if (next != null) {
            builder.append(",");
        }
    }
    return builder.toString();
}

最终解法

我的解法
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode resultNode = new ListNode();
        ListNode tail = resultNode;
        // 初始进位为0
        int carry = 0;
        while (l1 != null || l2 != null) {
            ListNode newNode = new ListNode();
            // 若其中有一个队列的next为空则以0代替
            int val1 = l1 == null ? 0 : l1.val;
            int val2 = l2 == null ? 0 : l2.val;

            // 每次都要计算进位(初始为0 相当于不用计算)
            int sum = val1 + val2 + carry;
            // 进位已经被加入结果,重置为0
            carry = 0;

            //计算出的结果大于等于10,那么只取余数,然后设置进位
            if (sum >= 10) {
                int r = sum % 10;
                carry = sum / 10;
                newNode.val = r;
            } else {
                //小于10 不用处理
                newNode.val = sum;
            }

            // 向尾部入列
            tail.next = newNode;
            tail = newNode;

            if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
        }
        // 若最终还有进位没有被消耗,则新增一位
        if (carry != 0) {
            tail.next = new ListNode(carry);
        }

        return resultNode.next;
    }
复杂度分析
  • 时间复杂度:O(max(m,n))其中 m和 n 分别为两个链表的长度。我们要遍历两个链表的全部位置,而处理每个位置只需要O(1) 的时间。
  • 空间复杂度:O(1)。注意返回值不计入空间复杂度。
官方解法
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;
    }
}
复杂度分析
  • 时间复杂度:O(max(m,n))其中 m和 n 分别为两个链表的长度。我们要遍历两个链表的全部位置,而处理每个位置只需要O(1) 的时间。
  • 空间复杂度:O(1)。注意返回值不计入空间复杂度。
总结

我和官方的解法差不多,但是官方的更加简洁一些,比如:不需要判断sum大于10小于10的情况,直接用sum % 10的结果即可,1%10 = 1 11%10=1 其实是一样的。

0

评论区