查看原文
其他

615,双指针解两数相加

博哥 数据结构和算法 2022-05-19

问题描述



来源:LeetCode第2题

难度:中等


给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。


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


示例 1:

输入: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

  • 题目数据保证列表表示的数字不含前导零


双指针解决



两个链表分别代表两个数字,链表的头节点表示的是个位数,如果从链表的头节点开始相加,符合我们常见的加法运算。


我们可以使用两个指针,开始的时候分别指向两个链表的头节点。用他们相加
和的个位数构造一个新的节点(因为一个节点只能存储一位数字),这两个指针每次运算完之后都要同时往后移一步,然后还要使用一个变量carry表示是否有进位。两个指针只要有一个不为空,或者carry不为0就继续循环,我们看个视频。

来看下代码

public ListNode addTwoNumbers(ListNode listNode1, ListNode listNode2) {
    //创建一个哑节点,他的指针指向新链表的头节点
    ListNode dummyNode = new ListNode(0);
    //preNode表示当前节点的前一个节点
    ListNode preNode = dummyNode;
    //表示两个节点相加进位的值,加法最多只进一位,所以carry要么是1要么是0
    int carry = 0;
    //两个链表只要有一个不为空,或者有进位就一直循环
    while (listNode1 != null || listNode2 != null || carry != 0) {
        //当前节点的累加值,需要加上前面进位的值
        int sum = carry;
        //如果第一个链表的当前节点不为空,加上第一个链表当前节点的值
        if (listNode1 != null) {
            sum += listNode1.val;
            listNode1 = listNode1.next;
        }
        //第二个链表,同上
        if (listNode2 != null) {
            sum += listNode2.val;
            listNode2 = listNode2.next;
        }
        //创建新的节点,preNode的next指针指向新的节点,因为链表节点
        //只能存储一位数字,所以这里要对sum求余,取个位数。
        preNode.next = new ListNode(sum % 10);

        //如果sum大于等于10,说明有进位,carry为1,
        //否则没有,carry为0
        carry = sum / 10;
        //更新preNode
        preNode = preNode.next;
    }
    return dummyNode.next;
}


递归方式解决



这题其实没有什么难度,我们还可以改成递归的方式,原理和上面一样,都是从前往后加,递归的终止条件是两个链表都为空,并且没有进位。来看下代码

public ListNode addTwoNumbers(ListNode listNode1, ListNode listNode2) {
    ListNode dummyNode = new ListNode(0);
    helper(dummyNode, listNode1, listNode2, 0);
    return dummyNode.next;
}

private void helper(ListNode preNode, ListNode listNode1, ListNode listNode2, int carry) {
    //只有两个链表都为空并且没有进位的时候才终止循环
    if (listNode1 == null && listNode2 == null && carry == 0)
        return;
    int sum = carry;
    //链表1中节点的值累加
    if (listNode1 != null) {
        sum += listNode1.val;
        listNode1 = listNode1.next;
    }
    //第二个链表,同上
    if (listNode2 != null) {
        sum += listNode2.val;
        listNode2 = listNode2.next;
    }
    //创建新的节点
    preNode.next = new ListNode(sum % 10);
    //更新carry
    carry = sum / 10;
    //继续递归
    helper(preNode.next, listNode1, listNode2, carry);
}


596,删除排序链表中的重复元素 II

595,删除排序链表中的重复元素

554,反转链表 II

502,分隔链表的解决方式


截止到目前我已经写了600多道算法题了,为了方便大家阅读,我把部分算法题整理成了pdf文档,目前有1000多页,大家可以在下面公众号“数据结构和算法”中回复关键字“pdf”即可获取下载链接。

你点的每个赞,我都认真当成了喜欢

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存