我想获取所有非连续的集合(即其元素在原始集合中不能相邻的任何子集):
go([1,2,3,4,5]) => [1],[1,3,5],[1,3],[1,4],[1,5],[2],[2,4],[2,5],[3]
我和以下人很接近
def go(ns)
return [[]] if ns == [] || ns == nil
return [[ns[0]]] if ns.length < 3
(0..ns.length-1).to_a.map do |i|
dup = go(ns[i+2..-1])
dup.map do |a|
[ns[i]] + a
end
end
end
这给出了:
[[[1, [3, 5]], [1, [4]], [1, [5]]], [[2, 4]], [[3, 5]], [[4]], [[5]]]
接近正确的结果(未命中[1],我只是弄乱了数组的连接,无法弄清楚如何使其平坦化。
请注意,元素可以是任何数字,它们只是无序的唯一数字,例如
[35, 40, 100, 54, 13]
答案 0 :(得分:1)
对于给定的n > 1
,我计算了一个包含所有数组的数组,这些数组包含一个或多个[a, ... , b]
形式的整数,其中a >= 1
,b <= n
以及每个相邻对的元素i, j
,j > i+1
。如果n = 1
,则返回[[1]]
。
我已经使用递归做到了这一点。 recurse(m,n)
计算所有此类数组的第一个元素为m
。
代码
def doit(n)
(1..n).reduce([]) { |a,m| a + recurse(m,n) }
end
def recurse(m,n)
return [[m]] if m >= n-1
(m+2..n).reduce([[m]]) { |a,p| a + recurse(p,n).map { |b| [m]+b } }
end
示例
doit 6
#=> [[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5], [1, 6],
# [2], [2, 4], [2, 4, 6], [2, 5], [2, 6],
# [3], [3, 5], [3, 6], [4], [4, 6], [5], [6]]
doit 8
#=> [[1], [1, 3], [1, 3, 5], [1, 3, 5, 7], [1, 3, 5, 8], [1, 3, 6],
# [1, 3, 6, 8], [1, 3, 7], [1, 3, 8], [1, 4], [1, 4, 6], [1, 4, 6, 8],
# [1, 4, 7], [1, 4, 8], [1, 5], [1, 5, 7], [1, 5, 8], [1, 6],
# [1, 6, 8], [1, 7], [1, 8],
# [2], [2, 4], [2, 4, 6], [2, 4, 6, 8], [2, 4, 7], [2, 4, 8], [2, 5],
# [2, 5, 7], [2, 5, 8], [2, 6], [2, 6, 8], [2, 7], [2, 8],
# [3], [3, 5], [3, 5, 7], [3, 5, 8], [3, 6], [3, 6, 8], [3, 7], [3, 8],
# [4], [4, 6], [4, 6, 8], [4, 7], [4, 8],
# [5], [5, 7], [5, 8],
# [6], [6, 8],
# [7],
# [8]]
说明
我相信,对于我来说,解释递归的工作方式的最清晰方法(尤其是对于使用递归的经验有限的读者而言)是在将代码puts
加入盐渍之后简单地执行代码。每当方法调用自身时,我都会缩进,而方法返回时,我都会缩进。
INDENT = 6
@pos = 0
def indent; @pos += INDENT; @s = ' '*@pos; end
def outdent; @pos -= INDENT; @s = ' '*@pos; end
def doit(n)
puts "doit: n=#{n}"
(1..n).reduce([]) do |a,m|
puts "a=#{a}"
puts "calling recurse(#{m},#{n})"
indent
a + recurse(m,n)
end
end
def recurse(m,n)
puts "\n#{@s}entered recurse(#{m},#{n})"
if m >= n-1
puts "#{@s}returning #{[[m]]} as m >= n-1\n\n"
outdent
return [[m]]
end
puts "#{@s}begin reduce"
a = (m+2..n).reduce([[m]]) do |a,p|
puts "#{@s} p=#{p}, a=#{a}"
puts "#{@s} calling recurse(#{p},#{n})"
indent
arr = recurse(p,n).map { |b| [m]+b }
puts "#{@s} back to recurse(#{m},#{n}) from recurse(#{p},#{n})"
puts "#{@s} array returned mapped to #{arr}"
a + arr
end
puts "#{@s}return #{a} from recurse(#{m},#{n})\n\n"
outdent
a
end
doit 6
doit: n=6
a=[]
calling recurse(1,6)
entered recurse(1,6)
begin reduce
p=3, a=[[1]]
calling recurse(3,6)
entered recurse(3,6)
begin reduce
p=5, a=[[3]]
calling recurse(5,6)
entered recurse(5,6)
returning [[5]] as m >= n-1
back to recurse(3,6) from recurse(5,6)
array returned mapped to [[3, 5]]
p=6, a=[[3], [3, 5]]
calling recurse(6,6)
entered recurse(6,6)
returning [[6]] as m >= n-1
back to recurse(3,6) from recurse(6,6)
array returned mapped to [[3, 6]]
return [[3], [3, 5], [3, 6]] from recurse(3,6)
back to recurse(1,6) from recurse(3,6)
array returned mapped to [[1, 3], [1, 3, 5], [1, 3, 6]]
p=4, a=[[1], [1, 3], [1, 3, 5], [1, 3, 6]]
calling recurse(4,6)
entered recurse(4,6)
begin reduce
p=6, a=[[4]]
calling recurse(6,6)
entered recurse(6,6)
returning [[6]] as m >= n-1
back to recurse(4,6) from recurse(6,6)
array returned mapped to [[4, 6]]
return [[4], [4, 6]] from recurse(4,6)
back to recurse(1,6) from recurse(4,6)
array returned mapped to [[1, 4], [1, 4, 6]]
p=5, a=[[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6]]
calling recurse(5,6)
entered recurse(5,6)
returning [[5]] as m >= n-1
back to recurse(1,6) from recurse(5,6)
array returned mapped to [[1, 5]]
p=6, a=[[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5]]
calling recurse(6,6)
entered recurse(6,6)
returning [[6]] as m >= n-1
back to recurse(1,6) from recurse(6,6)
array returned mapped to [[1, 6]]
return [[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5],
[1, 6]] from recurse(1,6)
a=[[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5], [1, 6]]
calling recurse(2,6)
entered recurse(2,6)
begin reduce
p=4, a=[[2]]
calling recurse(4,6)
entered recurse(4,6)
begin reduce
p=6, a=[[4]]
calling recurse(6,6)
entered recurse(6,6)
returning [[6]] as m >= n-1
back to recurse(4,6) from recurse(6,6)
array returned mapped to [[4, 6]]
return [[4], [4, 6]] from recurse(4,6)
back to recurse(2,6) from recurse(4,6)
array returned mapped to [[2, 4], [2, 4, 6]]
p=5, a=[[2], [2, 4], [2, 4, 6]]
calling recurse(5,6)
entered recurse(5,6)
returning [[5]] as m >= n-1
back to recurse(2,6) from recurse(5,6)
array returned mapped to [[2, 5]]
p=6, a=[[2], [2, 4], [2, 4, 6], [2, 5]]
calling recurse(6,6)
entered recurse(6,6)
returning [[6]] as m >= n-1
back to recurse(2,6) from recurse(6,6)
array returned mapped to [[2, 6]]
return [[2], [2, 4], [2, 4, 6], [2, 5], [2, 6]] from recurse(2,6)
a=[[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5], [1, 6],
[2], [2, 4], [2, 4, 6], [2, 5], [2, 6]]
calling recurse(3,6)
entered recurse(3,6)
begin reduce
p=5, a=[[3]]
calling recurse(5,6)
entered recurse(5,6)
returning [[5]] as m >= n-1
back to recurse(3,6) from recurse(5,6)
array returned mapped to [[3, 5]]
p=6, a=[[3], [3, 5]]
calling recurse(6,6)
entered recurse(6,6)
returning [[6]] as m >= n-1
back to recurse(3,6) from recurse(6,6)
array returned mapped to [[3, 6]]
return [[3], [3, 5], [3, 6]] from recurse(3,6)
a=[[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5], [1, 6],
[2], [2, 4], [2, 4, 6], [2, 5], [2, 6], [3], [3, 5], [3, 6]]
calling recurse(4,6)
entered recurse(4,6)
begin reduce
p=6, a=[[4]]
calling recurse(6,6)
entered recurse(6,6)
returning [[6]] as m >= n-1
back to recurse(4,6) from recurse(6,6)
array returned mapped to [[4, 6]]
return [[4], [4, 6]] from recurse(4,6)
a=[[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5], [1, 6],
[2], [2, 4], [2, 4, 6], [2, 5], [2, 6], [3], [3, 5], [3, 6], [4], [4, 6]]
calling recurse(5,6)
entered recurse(5,6)
returning [[5]] as m >= n-1
a=[[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5], [1, 6],
[2], [2, 4], [2, 4, 6], [2, 5], [2, 6], [3], [3, 5], [3, 6], [4], [4, 6], [5]]
calling recurse(6,6)
entered recurse(6,6)
returning [[6]] as m >= n-1
#=> [[1], [1, 3], [1, 3, 5], [1, 3, 6], [1, 4], [1, 4, 6], [1, 5], [1, 6],
# [2], [2, 4], [2, 4, 6], [2, 5], [2, 6], [3], [3, 5], [3, 6], [4], [4, 6],
# [5], [6]]