有关Array中元素的移位问题

周五遇到的一个元素移位问题,最后老大很漂亮地解决了,现在回头看,觉得很有必要记录下。

问题描述

场景类似这样:

给到一个数组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!