两数相加(二)

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

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

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

两数相加(二)_第1张图片

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

两数相加(二)_第2张图片

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

两数相加(二)_第3张图片

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

两数相加(二)_第4张图片

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

两数相加(二)_第5张图片

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

两数相加(二)_第6张图片

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

两数相加(二)_第7张图片

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

两数相加(二)_第8张图片

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

 

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

你可能感兴趣的:(两数相加(二))