402v /posts/leetcodeshi-zhan-add-two-numbers

LeetCode实战 - Add Two Numbers

最近在刷leetcode,对自己的算法思路做个简单的记录,希望最后回顾起来自己是有提高的。

通篇算法都是用Ruby语言实现,文内不再赘述。Markdown没有支持数学格式,所以时间复杂度的记法比较粗糙,见谅。

这一系列的文章可以在这里找到。


本期题目:

You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8

题目难度:中级

这道题刚开始没看懂。。。题目的意思是给两个链表分别代表两个非负数。数字的每一位按照逆序存储在链表的每个结点中。将这两个非负数相加同时返回一个相同结构的链表。

###多些时间可以少些Code 链表、数字相加,显然是一道考察编程的题,所以就越是要小心边界条件、逻辑分支。

  1. 反向链表的好处是从头结点直接相加,大等于10则下一位加一;
  2. 由于是非负整数,所以我们可以认为链表中至少有一个结点是有值的,这样就省去了很多麻烦;
  3. 题目没说是不是非负整数,姑且先按整数考虑,submit的时候跑case看看;
  4. 当其中一个链表走到头时,另一个链表剩余的位数可以直接拼接到结果链表中。注意如果之前一个相加刚好大等于10则需要剩余位数的第一位加一,后续几位也同理(如:234 + 34669991);
  5. 如果相加之后的最后一位大等于10,结果链表长度会等于两个链表长度的最大值加一,(如:333 + 667)

###还是要Code

一次提交成功!代码如下:

# Definition for singly-linked list.
# class ListNode
#     attr_accessor :val, :next
#     def initialize(val)
#         @val = val
#         @next = nil
#     end
# end

# @param {ListNode} l1
# @param {ListNode} l2
# @return {ListNode}
def add_two_numbers(l1, l2)
    decimal = 10 # 十进制
    
    carrybit = 0 # 进位标识符
    
    # 初始化结果链表头结点,个位相加
    sum_val = l1.val + l2.val
    l1 = l1.next
    l2 = l2.next
    
    carrybit = sum_val/decimal
    sum_val = sum_val%decimal
        
    sum_list = ListNode.new(sum_val)
    current_node = sum_list
    
    # 链表元素相加
    while l1 || l2 do
        sum_val = carrybit
        
        if l1 then
            sum_val += l1.val
            l1 = l1.next
        end
        
        if l2 then
            sum_val += l2.val
            l2 = l2.next
        end
        
        carrybit = sum_val/decimal
        sum_val = sum_val%decimal
        
        current_node.next = ListNode.new(sum_val)
        current_node = current_node.next
    end
    
    # 最后一位是否有进位?
    if carrybit > 0 then
        current_node.next = ListNode.new(carrybit)
        current_node = current_node.next
    end
    
    sum_list
end

在实现上经过了几个优化:

  1. 之前把l1或l2剩余结点的情况用单独的while处理,后来发现放到一个while里面做下if判断就好;

     if l1 then
         sum_val += l1.val
         l1 = l1.next
     end
    
  2. 用求余和取整代替用if判断是否需要进位;

     carrybit = sum_val/decimal
     sum_val = sum_val%decimal
    
  3. 将代表进制的变量单独抽离处理,初步看16进制和其他进制也可以用这个函数处理。

     decimal = 10 # 十进制
    

此题为第二题。

评论 · 0

还没有评论。