【每日一题Day254】LC445两数相加Ⅱ | 链表反转 栈

简介: 【每日一题Day254】LC445两数相加Ⅱ | 链表反转 栈

两数相加Ⅱ【LC445】

给定两个 非空链表 l1l2 来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。

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

原来是专题模拟

反转链表

2022/11/4

  • 思路:将链表1、链表2反转后进行求和,并使用变量记录进位,最后将结果再进行反转后返回
  • 实现
  • 如果有一个链表为空链表,那么将另一个链表返回
  • 将链表1、链表2反转得到新的头结点cur1、cur2
  • 使用变量cnt记录低位节点相加后的进位结果,使用cur记录求和后的结果
  • 当两个链表不都为空时,需要进行累加(val1+val2+cnt)%10得到新节点
  • 注意:需要处理空节点,空节点的值记为0
  • 更新:cnt = (val1+val2+cnt)/10
  • 最后判断是否存在进位,如果存在的话加在链表末尾
  • 最后将结果进行反转
  • 代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1 == null){
            return l2;
        }
        if (l2 == null){
            return l1;
        }
        ListNode cur1 = reverse(l1);
        ListNode cur2 = reverse(l2);
        int cnt = 0;
        ListNode dummyNode = new ListNode(0);
        ListNode cur = dummyNode;       
        while (cur1 != null || cur2 != null){
            int val1 = cur1 == null ? 0 : cur1.val;
            int val2 = cur2 == null ? 0 : cur2.val; 
            cur.next = new ListNode((cnt + val1 + val2) % 10);
            cnt = (cnt + val1 + val2 ) / 10;
            cur1 = cur1 == null ? null : cur1.next ;
            cur2 = cur2 == null ? null : cur2.next ;
            cur = cur.next;
        }
        if (cnt != 0){
            cur.next = new ListNode(cnt);
        }
        return reverse(dummyNode.next);
    }
    public ListNode reverse(ListNode head){
        ListNode dummyNode = new ListNode(0,head);
        ListNode cur = dummyNode.next;
        while (cur != null && cur.next != null){
            ListNode nextTemp = cur.next.next;
            cur.next.next = dummyNode.next;
            dummyNode.next = cur.next;
            cur.next = nextTemp;
        }
        return dummyNode.next;
    }
}

复杂度分析

  • 时间复杂度:O(N+M),其中 N和M分别是链表中的节点数。
  • 空间复杂度:O(1),返回值不计入空间复杂度

前后双指针

2022/11/5

思路:使用前后双指针将链表中的两数之后记录在数组中,然后倒序遍历数组,处理产生的进位,最后通过数组生成链表

实现

先将两个链表遍历一遍,统计其节点个数,记为n1,n2,使用数组nums记录数值

然后设置指针位于链表的起点,记为cur1,cur2

如果n1 > n2,那么将cur1先移动n1-n2步,并将数值记录在nums中

如果n2 > n1,那么将cur2先移动n1-n2步,并将数值记录在nums中

此时cur1和cur2位于相同位置,将链表中的两数进行相加操作,并将数值(val1+val2)记录在nums中

使用变量cnt记录低位的进行,然后倒序遍历数组处理进位

判断是否存在最高位进位,如果存在的话加在链表开头

最后通过nums数组构建链表

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1 == null){
            return l2;
        }
        if (l2 == null){
            return l1;
        }
        ListNode cur1 = l1;
        ListNode cur2 = l2;
        int n1 = 0, n2 = 0;
        // 统计个数
        while (cur1 != null){
            n1++;
            cur1 = cur1.next;
        }
        while (cur2 != null){
            n2++;
            cur2 = cur2.next;
        }
        cur1 = l1;
        cur2 = l2;
        int i = 0;
        int[] nums;
        // 移动后指针
        if (n1 > n2){
            nums = new int[n1];
            while (i < n1 - n2){
                nums[i++] = cur1.val;
                cur1 = cur1.next;
            }
        }else {
            nums = new int[n2];
            while (i < n2 - n1){
                nums[i++]= cur2.val;
                cur2 = cur2.next;
            }
        }
        // 链表相加
        while (cur1 != null && cur2 != null){
            nums[i++] = cur1.val + cur2.val;
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        // 处理进位
        int cnt = 0;
        for (i = nums.length - 1; i >= 0;i--){
            int tmp = (nums[i] + cnt) / 10;
            nums[i] = (nums[i] + cnt) % 10;
            cnt = tmp;
        }
        // 构造链表
        ListNode dummyNode = new ListNode(0);
        ListNode cur = dummyNode;
        if (cnt != 0){
            cur.next = new ListNode(cnt);
            cur = cur.next;
        }
        for(i = 0; i < nums.length; i++){
            cur.next = new ListNode(nums[i]);
            cur = cur.next;
        }
        return dummyNode.next;
    }
}

杂度分析

时间复杂度:O(N+M),其中 N和M分别是链表中的节点数。

空间复杂度:O(N+M),返回值不计入空间复杂度

2022/11/5

思路:由于链表中数位的顺序与加法的顺序相反,为了逆序处理所有数位,可以使用栈,把所有数字压入栈中,再依次取出相加,计算过程中注意进位的情况

实现:倒序构建链表,注意使用变量记录当前节点的下一节点,完成链表的构建

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if (l1 == null){
            return l2;
        }
        if (l2 == null){
            return l1;
        }
        ListNode cur1 = l1;
        ListNode cur2 = l2;
        Deque<ListNode> st1 = new LinkedList<>();
        Deque<ListNode> st2 = new LinkedList<>();
        while (cur1 != null ){
            st1.addFirst(cur1);
            cur1 = cur1.next;
        }
        while (cur2 != null){
            st2.addFirst(cur2);
            cur2 = cur2.next;
        }
        int cnt = 0;
        ListNode nn = null;
        while (!st1.isEmpty() || !st2.isEmpty() || cnt != 0){
            int val1 = st1.isEmpty() ? 0 :st1.pollFirst().val;
            int val2 = st2.isEmpty() ? 0 :st2.pollFirst().val;
            int val = (val1 + val2 + cnt) % 10;
            cnt = (val1 + val2 + cnt) / 10;
            ListNode ptr = new ListNode(val);
            ptr.next = nn;
            nn = ptr;
        }
        return nn;
    }
}


目录
相关文章
|
4月前
【Leetcode 2487】从链表中移除节点 —— 单调栈
解题思路:维持一个单调递增栈,当栈为空时,记录当前节点为头节点;否则当前节点为栈顶节点的后继节点
|
4月前
|
C++
数据结构01-线性结构-链表栈队列-栈篇
数据结构01-线性结构-链表栈队列-栈篇
|
2月前
|
Python
Python实现数据结构(如:链表、栈、队列等)。
Python实现数据结构(如:链表、栈、队列等)。
36 0
|
7月前
|
存储 机器学习/深度学习 算法
模拟实现单链表、双链表、栈、队列——数组模拟
我们在数据结构中都学到过单链表、双链表、栈和队列,当我们实现的时候时使用结构体指针实现的。定义一个结构体,结构体中存储指针变量和存放数值的变量。当然,C++的STL库中已经有实现好的栈和队列,我们可以直接用。但是在做算法题时,有时候我们会发现超出时间限制。原因是我们用STL库中的栈和队列容器时,效率相对来说较慢。我们这时就引出用数组模拟实现栈和队列。用数组模拟实现的使用起来效率更高、更方便。当然,我们也会讲到用数组模拟实现单链表和双链表。
28 0
|
10天前
|
存储
线性表、链表、栈和队列的初始化
线性表、链表、栈和队列的初始化
12 1
|
3月前
|
C语言
C语言(链表、栈、树)
C语言(链表、栈、树)
10 0
|
4月前
|
Go Python 算法
Python每日一练(20230412) 队列实现栈、二叉树序列化、交换链表节点
Python每日一练(20230412) 队列实现栈、二叉树序列化、交换链表节点
32 0
Python每日一练(20230412) 队列实现栈、二叉树序列化、交换链表节点
|
4月前
|
存储 数据安全/隐私保护 C++
数据结构01-线性结构-链表栈队列-队列篇
数据结构01-线性结构-链表栈队列-队列篇
|
9月前
|
算法
AcWing刷题(第二周)(链表,单调栈等......)
AcWing刷题(第二周)(链表,单调栈等......)
52 0
|
4月前
|
存储 算法
数据结构(数组、链表、栈、队列、树)(二)
数据结构(数组、链表、栈、队列、树)(二)