我有一个以升序或降序排序的数字数组,我想找到插入数字的索引,同时保留数组的顺序。如果数组为[1, 5, 7, 11, 51]
且要插入的数字为9
,我会期待3
,因此我可以执行[1, 5, 7, 11, 51].insert(3, 9)
。如果数组是[49, 32, 22, 11, 10, 8, 3, 2]
且要插入的数字是9
,我会期待5
所以我可以[49, 32, 22, 11, 10, 8, 3, 2].insert(5, 9)
在保留数组排序的同时,找到在这两个数组中插入9
的索引的最佳/最干净的方法是什么?
我写了这段有用的代码,但它并不是很漂亮:
array = [55, 33, 10, 7, 1]
num_to_insert = 9
index_to_insert = array[0..-2].each_with_index.map do |n, index|
range = [n, array[index.next]].sort
index.next if num_to_insert.between?(range[0], range[1])
end.compact.first
index_to_insert # => 3
答案 0 :(得分:3)
这不是一个好方法,但可能更清晰,因为您可以在升序或降序数组上使用方法insert_sorted(number)
,而不必担心它将被放置的索引:
module SortedInsert
def insert_index(number)
self.each_with_index do |element, index|
if element > number && ascending?
return index
end
if element < number && descending?
return index
end
end
length
end
def insert_sorted(number)
insert(insert_index(number), number)
end
def ascending?
first <= last
end
def descending?
!ascending?
end
end
在数组上使用它,如下所示:
array = [2, 61, 12, 7, 98, 64]
ascending = array.sort
descending = array.sort.reverse
ascending.extend SortedInsert
descending.extend SortedInsert
number_to_insert = 3
puts "Descending: "
p number_to_insert
p descending
p descending.insert_sorted(number_to_insert)
puts "Ascending: "
p number_to_insert
p ascending
p ascending.insert_sorted(number_to_insert)
这将给出:
Descending:
3
[98, 64, 61, 12, 7, 2]
[98, 64, 61, 12, 7, 3, 2]
Ascending:
3
[2, 7, 12, 61, 64, 98]
[2, 3, 7, 12, 61, 64, 98]
备注强>:
Array
对象的方法。insert_sorted(number)
,可以在排序位置插入数字。insert_index(number)
,它将提供需要插入数字的索引,以便结果数组保持排序。答案 1 :(得分:3)
Wand Maker的回答并不坏,但它有两个问题:
它对整个数组进行排序以确定它是升序还是降序。当你所要做的就是找到一个不等于之前的元素来比较第一个和最后一个元素以确定这一点时,这很愚蠢。在最糟糕的情况下,而不是, O ( n ) O (1) O ( n log n )。
在使用Array#index
时使用bsearch
。我们可以进行二进制搜索,而不是遍历整个数组,因为它已经排序。在最坏的情况下,这是 O (log n ),而不是 O ( n )。< / p>
我发现把它分成两种方法更清楚,但你当然可以把它变成一种:
def search_proc(ary, n)
case ary.first <=> ary.last
when 1 then ->(idx) { n > ary[idx] }
when -1 then ->(idx) { n < ary[idx] }
else raise "Array neither ascending nor descending"
end
end
def find_insert_idx(ary, n)
(0...ary.size).bsearch(&search_proc(ary, n))
end
p find_insert_idx([1, 5, 7, 11, 51], 9)
#=> 3
p find_insert_idx([49, 32, 22, 11, 10, 8, 3, 2], 9)
#=> 5
(我在这里使用Range#bsearch
。Array#bsearch
的工作方式相同,但使用范围返回索引更方便,效率更高,否则我们必须{ {1}}或其他什么。)
答案 2 :(得分:2)
这是我能想到的最简单的方法。
def find_insert_idx(ary, n)
is_asc = (ary.sort == ary)
if (is_asc)
return ary.index { |i| i > n }
else
return ary.index { |i| i < n }
end
end
p find_insert_idx([1,5,7,11,51], 9)
#=> 3
p find_insert_idx([49,32,22,11,10,8,3,2], 9)
#=> 5