首页 > 解决方案 > 无法在 Ruby 中正确格式化“添加两个数字”输出(单链表)

问题描述

尝试在 Ruby 中解决 leetcode 的“添加两个数字”问题(https://leetcode.com/problems/add-two-numbers/)。我知道我根本没有解决这个问题,只是想确保我可以首先以正确的“ListNode”格式获得我的输出。我试图添加的 ListNode 会不断地重写自己,因为它在 while 循环中,但我一直在努力解决这个问题,无法弄清楚如何以 leetcode 想要的方式获取输出。

任何帮助表示赞赏!

这是我的代码:

# class ListNode
#     attr_accessor :val, :next
#     def initialize(val = 0)
#         @val = val
#         @next = nil
#     end
# end

# @param {ListNode} l1
# @param {ListNode} l2
# @return {ListNode}

def add_two_numbers(l1, l2)
    current_output = head = ListNode.new()
    while l1.next != nil
        sum = l1.val + l2.val
        if current_output.next != nil
            current_output = current_output.next
        else
            current_output.next = ListNode.new(sum)
            current_output.next = current_output.next.next
        end

        l1.val = l1.next.val
        l1.next = l1.next.next
        l2.val = l2.next.val
        l2.next = l2.next.next
    end
    last_sum = l1.val + l2.val
    #current_output.next = ListNode.new(last_sum)
    return current_output 
end

注意:它要求输出是 ListNode 对象,所以我不能创建自己的 LinkedList 类

标签: rubysingly-linked-list

解决方案


经典解决方案

def add_two_numbers(l1, l2)
  head = ListNode.new
  carry = 0
  curr = head

  until l1.nil? && l2.nil? && carry.zero?
    v1 = l1&.val || 0
    v2 = l2&.val || 0
    carry, digit = (v1 + v2 + carry).divmod(10)
    curr.next = ListNode.new(digit)
    curr = curr.next
    l1 = l1&.next
    l2 = l2&.next
  end

  head.next
end

请注意l1l2可能有不同的长度,因此您应该在两个节点都变为 时结束循环nil

如果您不知道语法obj&.mthd,则称为“安全导航”,这意味着如果objnil,则立即返回nil而不调用mthd它。如果obj不是nil,则返回返回的任何内容obj.mthd

作弊

您可以计算出每个列表表示的整数,将它们相加,然后根据总和构建结果列表。

# Monkey-patch ListNode
# to make a list enumerable,
# so that we can call `reduce` on it.
ListNode.class_eval do
  include Enumerable

  def each(&block)
    return enum_for(:each) unless block
    block.(@val)
    @next.each(&block) if @next
  end
end

def add_two_numbers(l1, l2)
  n1 = l1.reduce(""){|s, n| "#{n}#{s}"}.to_i
  n2 = l2.reduce(""){|s, n| "#{n}#{s}"}.to_i

  head = ListNode.new
  (n1 + n2).digits.reduce(head) do |prev_node, digit|
    ListNode.new(digit).tap{|node| prev_node.next = node}
  end

  head.next
end

推荐阅读