无法在 Ruby 中正确格式化 "Add Two Numbers" 输出(单链表)
Can't format "Add Two Numbers" output correctly in Ruby (Singly Linked List)
试图在 Ruby (https://leetcode.com/problems/add-two-numbers/) 中解决 leetcode 的 "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 class
这是一个对两个链表求和的代码,然后我将把它分解,这样你就可以参与其中并使用它们,但是它没有经过很好的测试,因为我是在入侵 [=27 之后才写的=] 博客 post 并对其进行少量编辑:
class Node
attr_accessor :value, :next
def initialize(value, next_node)
@value = value
@next = next_node
end
end
class LinkedList
include Enumerable
def initialize
@head = nil
end
def add_to_list(value)
return @head = Node.new(value, nil) unless @head
current_node = @head
while current_node.next != nil
current_node = current_node.next
end
current_node.next = Node.new(value, nil)
end
def each
current = @head
while current
yield current.value
current = current.next
end
end
def to_i
self.reduce(""){ |s, l| "#{l}#{s}" }.to_i
end
end
list1 = LinkedList.new
list2 = LinkedList.new
sum = LinkedList.new
list1.add_to_list(2) # => #<Node:0x000055951cb54940 @value=2, @next=nil>
list1.add_to_list(4) # => #<Node:0x000055951cb545f8 @value=4, @next=nil>
list1.add_to_list(3) # => #<Node:0x000055951cb543a0 @value=3, @next=nil>
list2.add_to_list(5) # => #<Node:0x000055951cb54170 @value=5, @next=nil>
list2.add_to_list(6) # => #<Node:0x000055951cb7bf40 @value=6, @next=nil>
list2.add_to_list(4) # => #<Node:0x000055951cb7bd10 @value=4, @next=nil>
result = list1.to_i + list2.to_i # => 807
result.digits.each do |i|
sum.add_to_list(i)
end
puts list1.to_i # => nil
puts list2.to_i # => nil
puts sum.to_i # => nil
# >> 342
# >> 465
# >> 807
上面代码中下面是链表节点的定义:
class Node
attr_accessor :value, :next
def initialize(value, next_node)
@value = value
@next = next_node
end
end
该节点有一个值属性和一个指向链表中它后面的节点的指针。
在这种情况下,让我们分解一下只有两个方法的链表:
第一个是 add_to_list
:
def add_to_list(value)
return @head = Node.new(value, nil) unless @head
current_node = @head
while current_node.next != nil
current_node = current_node.next
end
current_node.next = Node.new(value, nil)
end
它接受一个整数作为值,然后在链表中为它创建一个节点。
第二种方法是to_i
,它将链表backward
转换为一个整数,所以稍后我们可以做list1.to_i + list2.to_i
,它给出了两个列表的总和:
def each
current = @head
while current
yield current.value
current = current.next
end
end
def to_i
self.reduce(""){ |s, l| "#{l}#{s}" }.to_i
end
现在让我们来看看进行实际计算的代码:
- 这里是
list1, list2, and the sum lists
的初始化:
list1 = LinkedList.new
list2 = LinkedList.new
sum = LinkedList.new
list1.add_to_list(2) # => #<Node:0x000055951cb54940 @value=2, @next=nil>
list1.add_to_list(4) # => #<Node:0x000055951cb545f8 @value=4, @next=nil>
list1.add_to_list(3) # => #<Node:0x000055951cb543a0 @value=3, @next=nil>
list2.add_to_list(5) # => #<Node:0x000055951cb54170 @value=5, @next=nil>
list2.add_to_list(6) # => #<Node:0x000055951cb7bf40 @value=6, @next=nil>
list2.add_to_list(4) # => #<Node:0x000055951cb7bd10 @value=4, @next=nil>
- 这里是
list1, and list2
: 的实际总和
result = list1.to_i + list2.to_i # => 807
- 这里是
result
整数值到链表的转换:
result.digits.each do |i|
sum.add_to_list(i)
end
- 这里是打印出来的
list1, list2, and sum
个变量的内容:
puts list1.to_i # => nil
puts list2.to_i # => nil
puts sum.to_i # => nil
# >> 342
# >> 465
# >> 807
所以在你的 add_two_numbers
问题方法中,你想要的只是以正确的方式将两个链表转换为整数,然后求和,然后将得到的整数转换为链表列出将作为最终解决方案返回的列表,并确保 运行 足够的测试用例并测试角落用例。
经典解法
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
注意l1
和l2
可能有不同的长度,所以你应该在两个节点都变成nil
时结束循环。
如果你不知道语法 obj&.mthd
,它被称为 "safe navigation",这意味着如果 obj
是 nil
,return nil
立即调用 mthd
。如果 obj
不是 nil
,return 无论如何 obj.mthd
returns.
作弊
您可以算出每个列表代表的整数,将它们相加,并根据总和构建结果列表。
# 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
试图在 Ruby (https://leetcode.com/problems/add-two-numbers/) 中解决 leetcode 的 "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 class
这是一个对两个链表求和的代码,然后我将把它分解,这样你就可以参与其中并使用它们,但是它没有经过很好的测试,因为我是在入侵 [=27 之后才写的=] 博客 post 并对其进行少量编辑:
class Node
attr_accessor :value, :next
def initialize(value, next_node)
@value = value
@next = next_node
end
end
class LinkedList
include Enumerable
def initialize
@head = nil
end
def add_to_list(value)
return @head = Node.new(value, nil) unless @head
current_node = @head
while current_node.next != nil
current_node = current_node.next
end
current_node.next = Node.new(value, nil)
end
def each
current = @head
while current
yield current.value
current = current.next
end
end
def to_i
self.reduce(""){ |s, l| "#{l}#{s}" }.to_i
end
end
list1 = LinkedList.new
list2 = LinkedList.new
sum = LinkedList.new
list1.add_to_list(2) # => #<Node:0x000055951cb54940 @value=2, @next=nil>
list1.add_to_list(4) # => #<Node:0x000055951cb545f8 @value=4, @next=nil>
list1.add_to_list(3) # => #<Node:0x000055951cb543a0 @value=3, @next=nil>
list2.add_to_list(5) # => #<Node:0x000055951cb54170 @value=5, @next=nil>
list2.add_to_list(6) # => #<Node:0x000055951cb7bf40 @value=6, @next=nil>
list2.add_to_list(4) # => #<Node:0x000055951cb7bd10 @value=4, @next=nil>
result = list1.to_i + list2.to_i # => 807
result.digits.each do |i|
sum.add_to_list(i)
end
puts list1.to_i # => nil
puts list2.to_i # => nil
puts sum.to_i # => nil
# >> 342
# >> 465
# >> 807
上面代码中下面是链表节点的定义:
class Node
attr_accessor :value, :next
def initialize(value, next_node)
@value = value
@next = next_node
end
end
该节点有一个值属性和一个指向链表中它后面的节点的指针。
在这种情况下,让我们分解一下只有两个方法的链表:
第一个是 add_to_list
:
def add_to_list(value)
return @head = Node.new(value, nil) unless @head
current_node = @head
while current_node.next != nil
current_node = current_node.next
end
current_node.next = Node.new(value, nil)
end
它接受一个整数作为值,然后在链表中为它创建一个节点。
第二种方法是to_i
,它将链表backward
转换为一个整数,所以稍后我们可以做list1.to_i + list2.to_i
,它给出了两个列表的总和:
def each
current = @head
while current
yield current.value
current = current.next
end
end
def to_i
self.reduce(""){ |s, l| "#{l}#{s}" }.to_i
end
现在让我们来看看进行实际计算的代码:
- 这里是
list1, list2, and the sum lists
的初始化:
list1 = LinkedList.new
list2 = LinkedList.new
sum = LinkedList.new
list1.add_to_list(2) # => #<Node:0x000055951cb54940 @value=2, @next=nil>
list1.add_to_list(4) # => #<Node:0x000055951cb545f8 @value=4, @next=nil>
list1.add_to_list(3) # => #<Node:0x000055951cb543a0 @value=3, @next=nil>
list2.add_to_list(5) # => #<Node:0x000055951cb54170 @value=5, @next=nil>
list2.add_to_list(6) # => #<Node:0x000055951cb7bf40 @value=6, @next=nil>
list2.add_to_list(4) # => #<Node:0x000055951cb7bd10 @value=4, @next=nil>
- 这里是
list1, and list2
: 的实际总和
result = list1.to_i + list2.to_i # => 807
- 这里是
result
整数值到链表的转换:
result.digits.each do |i|
sum.add_to_list(i)
end
- 这里是打印出来的
list1, list2, and sum
个变量的内容:
puts list1.to_i # => nil
puts list2.to_i # => nil
puts sum.to_i # => nil
# >> 342
# >> 465
# >> 807
所以在你的 add_two_numbers
问题方法中,你想要的只是以正确的方式将两个链表转换为整数,然后求和,然后将得到的整数转换为链表列出将作为最终解决方案返回的列表,并确保 运行 足够的测试用例并测试角落用例。
经典解法
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
注意l1
和l2
可能有不同的长度,所以你应该在两个节点都变成nil
时结束循环。
如果你不知道语法 obj&.mthd
,它被称为 "safe navigation",这意味着如果 obj
是 nil
,return nil
立即调用 mthd
。如果 obj
不是 nil
,return 无论如何 obj.mthd
returns.
作弊
您可以算出每个列表代表的整数,将它们相加,并根据总和构建结果列表。
# 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