【算法攻坚】链表两数相加

简介: 【算法攻坚】链表两数相加

刷题两天小结


很多题目还是直接没有思路,如果只是暴力破解又没有什么作用,有的题目思考很长时间也是做不出来,


刷题顺序也没有什么规律,看到拿到刷哪个,搜了下资料,刷题比较少的可以最开始从头开始刷,目前先按照这个规律刷150题左右


1、建议未刷过题的新人按着顺序来。前 150 题覆盖了很多经典题目和知识点,指针法类如『3 sum』系列,动规类如『regex matching』,搜索类题目如『Sodoku Solver』。

2、基本熟悉知识点(图、树、堆、栈、链表、哈希表、记忆搜索、动态规划、指针法、并查集等)后,可以一类类标签强攻。Leetcode 右侧的标签系统虽然未必 100% 完整,但是大致分类做得还不错。

3、面试前的一个月可以只做『Hard』标签的题目,因为一般两遍之后对于大部分『Medium』难度以下的题目都是肌肉记忆了。多练习『Hard』类题目可以让自己的思路更开阔,因为很多题目使用的奇淫巧技让人惊讶,比如 Leetcode 精心设计连续题号的『84. Largest Rectangle in Histogram』、『85. Maximal Rectangle』。


题目


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


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

你可以假设除了数字 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]


思路


链表问题一般都会使用虚拟表头来控制循环,类似Java的AQS中哨兵节点,都是为了方便递归或者迭代


这道题目也是这个思路


  1. 根据最长的链表来控制整体迭代次数


  1. 添加虚拟节点用于后面建立链表


  1. 相同index下数字之和,如果某个链表没有这个index,默认给0,不会影响求和,如果是求乘机,默认给1


  1. 当前链表节点的值为上个节点之和的进位与当前index的两个节点之和,然后再取模,商用来进位


  1. 当两个链表都迭代完成,如果商数还是大于0, 说明两个链表最后的节点之和大于10,需要继续进位,所以需要多创建一个节点


public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    //冗余节点,为了循环方便
    ListNode preNode = new ListNode(-1);
    ListNode currentNode = preNode;
    int shang = 0;
    //长度以最长的链表为主
    while (l1 != null || l2 != null) {
        int sum = getSum(l1, l2);
        //创建下一个节点
        currentNode.next = new ListNode((sum + shang) % 10);
        shang = (sum + shang) / 10;
        //当前节点指向下一个节点
        currentNode = currentNode.next;
        //两个链表分别往后迭代
        l1 = (l1 == null) ? null : l1.next;
        l2 = (l2 == null) ? null : l2.next;
    }
    //链表长度内加完之后,最后余数还是大于0,说明扩展位数
    if (yushu > 0) {
        currentNode.next = new ListNode(yushu);
    }
    return preNode.next;
}
/**
 * 节点为null时按照值为0处理
 */
private static int getSum(ListNode l1, ListNode l2) {
    int val1 = l1 == null ? 0 : l1.val;
    int val2 = l2 == null ? 0 : l2.val;
    return val1 + val2;
}

执行用时:2 ms, 在所有 Java 提交中击败了94.18%的用户

内存消耗:38.6 MB, 在所有 Java 提交中击败了61.42%的用户


这道题加上调试,差不多也用了一个多小时,终于AC后感觉还是不错的,

然后再查看下官网的题解

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode pre = new ListNode(0);
        ListNode cur = pre;
        int carry = 0;
        while(l1 != null || l2 != null) {
            int x = l1 == null ? 0 : l1.val;
            int y = l2 == null ? 0 : l2.val;
            int sum = x + y + carry;
            carry = sum / 10;
            sum = sum % 10;
            cur.next = new ListNode(sum);
            cur = cur.next;
            if(l1 != null)
                l1 = l1.next;
            if(l2 != null)
                l2 = l2.next;
        }
        if(carry == 1) {
            cur.next = new ListNode(carry);
        }
        return pre.next;
    }
}

执行用时:2 ms, 在所有 Java 提交中击败了94.18%的用户

内存消耗:38.7 MB, 在所有 Java 提交中击败了42.04%的用户


时间和内存几乎一样, 其实整体思路差不多,官网给出了虚拟节点的作用定义:


小技巧:对于链表问题,返回结果为头结点时,通常需要先初始化一个预先指针 pre,该指针的下一个节点指向真正的头结点head。使用预先指针的目的在于链表初始化时无可用节点值,而且链表构造过程需要指针移动,进而会导致头指针丢失,无法返回结果。


同时在其他评论发现了另一个优化点


如果把 carry = sum / 10; 换成 carry = sum >9 ? 1 : 0 ; 这样 速度会快很多


结果:


执行用时:1 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:38.5 MB, 在所有 Java 提交中击败了75.16%的用户

这里主要是因为除法运算相对比较耗时的原因,同时题目本身都是整数可以这么特殊处理

类似的优化手段还有位运算替代乘除法等


目录
相关文章
|
1月前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
65 1
|
1月前
|
算法 索引
❤️算法笔记❤️-(每日一刷-141、环形链表)
❤️算法笔记❤️-(每日一刷-141、环形链表)
45 0
|
1月前
|
算法
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
【❤️算法笔记❤️】-(每日一刷-876、单链表的中点)
43 0
|
1月前
|
算法
【❤️算法笔记❤️】-每日一刷-23、合并 K 个升序链表
【❤️算法笔记❤️】-每日一刷-23、合并 K 个升序链表
32 0
|
1月前
|
存储 算法
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
87 0
|
17天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
17天前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
1月前
|
存储 缓存 算法
经典算法之链表篇(三)
经典算法之链表篇(三)
|
1月前
|
算法
经典算法之链表篇(二)
经典算法之链表篇(二)
|
1月前
|
算法 索引
经典算法之链表篇
经典算法之链表篇