周五遇到的一个元素移位问题,最后老大很漂亮地解决了,现在回头看,觉得很有必要记录下。
问题描述
场景类似这样:
给到一个数组A,数组B,B是A中连续几个元素的无序组合,比如 A= [2, 4, 5, 1, 9, 0], B= [5, 9, 1],B是A中5,1,9 这三个连续的值无序组合成的, 现在需要生成一个新的数组,将B在A中原先的对应元素5,1, 9位置前移或者后移。
比如前移一个,生成[2, 5, 1, 9, 4, 0],后移一个,生成[2, 4, 0, 5, 1, 9],如果5已经是第一个元素,则不做前移,9如果是最后一个元素,则不做后移。
这里有一个前提条件,A中没有重复的元素,也就是A.uniq == A 。
解决思路
解决思路如下:【盗用下老大的思路:P】
遍历A中的元素,如果该元素属于B,则塞进一个新的数组中,不属于B,则单独生成一个单一元素的数组,然后把这些生成的新数组组合起来,最后生成一个大的数组,这个内嵌数组的大数组长这样:[[2], [4], [5, 1, 9], [0]], 这样只需要针对大数组进行元素互换即可。
我这表达可能还不够清晰,看代码实现吧!
代码实现
定义一个method reorder,这里我们用step来表示移位,step为正,则向前移动step步,step为负,则向后移动step步,有关参数部分的检验,这里略去。
def reorder(current, part ,step)
order_index = nil
new_order = []
current.each do |item|
if part.include?(item)
if order_index
new_order[order_index] << item
else
new_order << [item]
order_index = new_order.count - 1
end
else
new_order << [item]
end
end
new_index = order_index + step
if new_index >= 0 && new_index < current.count
new_order[order_index], new_order[new_index] = new_order[new_index], new_order[order_index]
end
new_order.flatten!
end
基本跟思路走的。
用一两个例子测试一下:
a = [65, 34, 47, 29, 72, 74, 15, 52, 90, 23, 31, 56, 89, 3, 85, 55, 57, 27, 20]
b1 = [90, 23, 31, 15, 52]
b2 = [57]
b3 = [65]
b4 = [20]
p reorder(a, b1, 2)
=> [65, 34, 47, 29, 15, 52, 90, 23, 31, 72, 74, 56, 89, 3, 85, 55, 57, 27, 20]
p reorder(a, b2, -2)
=> [65, 34, 47, 29, 72, 74, 15, 52, 90, 23, 31, 56, 89, 3, 85, 55, 27, 20, 57]
p reorder(a, b3, 1)
=> [65, 34, 47, 29, 72, 74, 15, 52, 90, 23, 31, 56, 89, 3, 85, 55, 57, 27, 20]
p reorder(a, b4, -1)
=> [65, 34, 47, 29, 72, 74, 15, 52, 90, 23, 31, 56, 89, 3, 85, 55, 57, 27, 20]
b1是a中[15, 52, 90, 23, 31]这5个元素无序组合而成,reorder(a, b1, 2) ,则需要将这5个元素往前移动两位,通过最后生成的新数组,可以看到确实移动了两位,15前面的72,74都移动到了31的后面。
b2是含单一元素的数组,一样适用。
b3, b4是特例,分别是a的第一个和最后一个元素,第一个元素无法向前移动一位,最后一个元素也无法向后移动一位,所以生成的new_order与a一样。
OK!