• 两数相加(二)--链表


    给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储一位数字。

    如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

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

    示例:

    输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
    输出:7 -> 0 -> 8
    原因:342 + 465 = 807

    解法一

    思路:

    • 标签: 链表
    • 将两个链表看成是相同长度的进行遍历,如果一个链表较短则在前面补0,比如987 + 23 = 987 + 023 = 1010
    • 每一位计算的同时需要考虑上一位的进位问题,而当前位计算结束后同样需要更新进位值
    • 如果两个链表全部遍历完毕后,进位值为1 ,则在新链表最前方添加节点1
    • 小技巧: 对于链表问题,返回结果为头节点时,通常需要先初始化一个预先指针pre,该指针的下一个节点指向真正的头节点head . 使用预先指针的目的在于链表初始化时无可用节点值,而且链表构造过程需要指针的移动,进而会导致头指针丢失,无法返回结果

    下面我们一一图解上面过程:

    (1)初始化pre指针,并让cur也指向都指向头节点head,以及进位carry初始化为0

    (2)利用上面思路l1.value + l2.value + carry,并对10取余,取整

    (3)利用7+3 = 10 ,carry = 1, sum = 0,并且平移节点l1,l2,cur

    (4)经过l1.value + l2.value + carry = 11,carry = sum/10 = 1,进位值为1,余值为sum % 10 = 1

    (5)计算之后,开始平移l1,l2,cur

    (6) 经过l1.value + l2.value + carry = 11,carry = sum/10 = 1,进位值为1,余值为sum % 10 = 0(实际存入链表)

    (7)计算之后平移l1,l2,cur,没有位数的,补0

    (8)链表遍历结束,进位为1,添加节点,并去除头节点

    (9)去除头节点0之后,也就是结果为0101,逆转过来为1010,满足要求.

    下面整个代码:

    public class ListNode {
          int val;
          ListNode next;
          ListNode(int x) { val = x; }
     }
    
    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;
        }
    }

    解法二

    抛弃解法一的思想:

    • 新建节点的class,包括该节点的值以及指向下一个节点的指针
    • 新建链表result,用于输出结果
    • 此不需要进位值标志carry,而是如果total > 10,让l1.value加1(或者l2.value加1),然后循环遍历即可

    首先我们新建节点的class,如下:

    public class ListNode {
        public var val: Int
        public var next: ListNode?
        public init(_ val: Int) {
            self.val = val
            self.next = nil
        }
    }

    下面是核心代码,已在leetcode上成功运行.

    func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
        var result: ListNode? = nil
        if l1 == nil && l2 == nil {
            return result
        }
        
        var s1 = l1
        var s2 = l2
        var total = (s1?.val ?? 0) + (s2?.val ?? 0)
        if total < 10 {
            s1 = s1?.next
        } else {
            total = total % 10
            s1 = s1?.next ?? ListNode.init(0)
            s1!.val = s1!.val + 1
        }
        
        result = ListNode.init(total)
        s2 = s2?.next
        result!.next = addTwoNumbers(s1, s2)
        return result
    }

    以上就是别致的两数之和,关于自己解决此类方法的思想和代码,希望对大家有所帮助!!!

  • 相关阅读:
    UML学习——用例图(二)
    servlet相关生命周期(二)
    UML 学习——UML概述(一)
    servlet概述(一)
    java 核心编程——线程之线程控制(五)
    java 核心编程——线程之线程池(ExecutorService)(四)
    java 核心编程——线程之线程组(四)
    java 核心编程——线程之定时器(TimerTask)(三)
    java 核心编程——线程之线程的开发方法(二)
    java 核心编程——线程之线程的基本概念(一)
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/11715023.html
Copyright © 2020-2023  润新知