将两个有序数组合并为一个有序数组

时间:2018-06-19 04:34:01

标签: arrays ruby

我正在编写一个方法,它接受两个排序的数组,我希望它返回一个合并的数组,其中所有值都已排序。鉴于以下两个数组:

array_one = [3, 4, 8]
array_two = [1, 5, 7]

我希望我的merge_arrays方法返回:

[1, 3, 4, 5, 7, 8]

我目前的算法如下:

def merge_arrays(array_one, array_two)
  merged_array_size = array_one.length + array_two.length
  merged_array = []

  current_index_on_one = 0
  current_index_on_two = 0
  current_merged_index = 0

  for i in (0..merged_array_size - 1)
    if array_one[current_index_on_one] < array_two[current_index_on_two]
      merged_array[current_merged_index] = array_one[current_index_on_one]
      current_index_on_one += 1
      current_merged_index += 1
    else
      merged_array[current_merged_index] = array_two[current_index_on_two]
      current_index_on_two += 1
      current_merged_index += 1
    end
  end

  return merged_array
end

我收到错误'未定义的方法`&lt;'为零:NilClass'。我不明白条件是如何收到这个。我调整了条件中的变量,它们给出了true或false值。我不确定是什么导致了这个错误。

6 个答案:

答案 0 :(得分:4)

也许我错过了这一点,但你可以做到:

(array_one + array_two).sort
=> [1, 3, 4, 5, 7, 8]

答案 1 :(得分:2)

  

我收到错误&#39;未定义的方法`&lt;&#39;为零:NilClass&#39;。我不明白条件是如何收到的。

首先将索引0与索引0进行比较:

[3, 4, 8]   [1, 5, 7]
 0-----------0          #=> 3 < 1

然后将下限值的索引递增1:

[3, 4, 8]   [1, 5, 7]
 0--------------1       #=> 3 < 5

等等:

[3, 4, 8]   [1, 5, 7]
    1-----------1       #=> 4 < 5

[3, 4, 8]   [1, 5, 7]
       2--------1       #=> 8 < 5

[3, 4, 8]   [1, 5, 7]
       2-----------2    #=> 8 < 7

那时你得到:

[3, 4, 8]   [1, 5, 7]
       2--------------3 #=> 8 < nil

索引3超出了数组的范围,因此array_two[current_index_on_two]返回nil并且:

if array_one[current_index_on_one] < array_two[current_index_on_two]
  # ...
end

变为

if 8 < nil
  # ...
end

导致ArgumentError(comparison of Integer with nil failed)。如果nil在左侧,则您获得NoMethodError (undefined method `<' for nil:NilClass)

答案 2 :(得分:1)

这是您使用递归编写merge的一种方法。请注意,如您所指定的,两个输入必须已经排序,否则输出将无效。输入的大小可能不同。

def merge (xs, ys)
  if xs.empty?
    ys
  elsif ys.empty?
    xs
  else
    x, *_xs = xs
    y, *_ys = ys
    if x < y
      [x] + (merge _xs, ys)
    else
      [y] + (merge xs, _ys)
    end
  end
end

merge [ 1, 3, 4, 6, 8, 9 ], [ 0, 2, 5, 7 ]
# => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

答案 3 :(得分:0)

假设您有两个已排序的数组。您需要使用递归创建管道来处理每个数组。检查每次迭代看 任一数组的索引 0中的值较低,从数组中删除该数值并将该值附加到result数组。

def merge_arrays(a, b)
  # build a holder array that is the size of both input arrays O(n) space
  result = []

  # get lower head value
  if a[0] < b[0]
    result << a.shift
  else
    result << b.shift
  end

  # check to see if either array is empty
  if a.length == 0
    return result + b
  elsif b.length == 0
    return result + a
  else
    return result + merge_arrays(a, b)
  end
end 

> a = [3, 4, 6, 10, 11, 15]
> b = [1, 5, 8, 12, 14, 19]
> merge_arrays(a, b)
#=> [1, 3, 4, 5, 6, 8, 10, 11, 12, 14, 15, 19]

答案 4 :(得分:0)

我对您的代码进行了细微更改,以使其正常工作。请参阅内部的评论。

array_one = [2, 3, 4, 8, 10, 11, 12, 13, 15]
array_two = [1, 5, 6, 7, 9, 14]

def merge_arrays(array_one, array_two) 
  array_one, array_two = array_two, array_one if array_one.length > array_two.length # (1) swap arrays to make satement (3) work, need array_two always be the longest
  merged_array_size = array_one.length + array_two.length
  merged_array = []

  current_index_on_one = 0
  current_index_on_two = 0
  current_merged_index = 0

  for i in (0...merged_array_size-1) # (2) three points to avoid the error
    if (!array_one[current_index_on_one].nil? && array_one[current_index_on_one] < array_two[current_index_on_two]) # (3) check also if array_one is nil
      merged_array[current_merged_index] = array_one[current_index_on_one]
      current_index_on_one += 1
      current_merged_index += 1
    else
      merged_array[current_merged_index] = array_two[current_index_on_two]
      current_index_on_two += 1
      current_merged_index += 1
    end
  end
  merged_array[current_merged_index] = array_one[current_index_on_one] || array_two[current_index_on_two] # (4) add the missing element at the end of the loop, looks what happen if you comment out this line
  return merged_array
end

p merge_arrays(array_one, array_two)
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

错误即将发生,因为循环正在向前迈出一步。解决方案是先停止并在循环结束时插入缺少的元素。

它也适用于:

# for i in (1...merged_array_size)
# and
# for i in (1..merged_array_size-1)
# and
# (merged_array_size-1).times do

答案 5 :(得分:0)

arr1 = [3, 4, 8,  9, 12]
arr2 = [1, 5, 7,  8, 13]

arr = [arr1, arr2]
idx = [0, 0]

(arr1.size + arr2.size).times.with_object([]) do |_,a|
  imin = [0, 1].min_by { |i| arr[i][idx[i]] || Float::INFINITY }
  a << arr[imin][idx[imin]]
  idx[imin] += 1
end
  #=> [1, 3, 4, 5, 7, 8, 8, 9, 12, 13]