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

两数相加Ⅱ【LC445】

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

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

img
原来是专题模拟

反转链表

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;
        
        }
    
    }
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值