使用Ruby和递归查找所有可能的排列

使用Ruby和递归查找所有可能的排列,ruby,arrays,Ruby,Arrays,我一直在尝试解决一个简单的测验问题,用Ruby和递归找到字符串的所有可能排列 我有以下Ruby代码: def permutation(string) return [string] if string.size < 2 chr = string.chars.first perms = permutation(string[1..-1]) result = [] for perm in perms for i in (0..perm.size)

我一直在尝试解决一个简单的测验问题,用Ruby和递归找到字符串的所有可能排列

我有以下Ruby代码:

def permutation(string)
  return [string] if string.size < 2

  chr    = string.chars.first
  perms  = permutation(string[1..-1])

  result = []

  for perm in perms
    for i in (0..perm.size)
      result << (perm[0..i] + chr + perm[i..-1])
    end
  end

  return result  
end
从理论上讲,这应该是一个非常简单和直接的问题,但我肯定我做错了什么。很可能是循环的范围。我知道Ruby数组类有实例方法置换来实现这一点,但我正在尝试解决它以供练习

请注意,当前实现的复杂性为O(N!)。是否有进一步提高性能的方法

您可以使用:

更新不使用usign
数组#置换

def permutation(string)
  return [''] if string.empty?

  chrs = string.chars
  (0...string.size).flat_map { |i|
    chr, rest = string[i], string[0...i] + string[i+1..-1]
    permutation(rest).map { |sub|
      chr + sub
    }
  }
end

permutation('abc')
# => ["abc", "acb", "bac", "bca", "cab", "cba"]
perms = ["b"]

要了解困难可能是什么,让我们用一个更简单的例子来尝试:

string = "ab"
您想要的结果是
[“ab”,“ba”]
。让我们看看你得到了什么:

string.size #=> 2
所以我们什么时候不回来

return [string] if string.size < 2
  #=> return ["ab"] if "ab".size < 2
请注意,更直接的计算方法如下:

chr = string[0]  #=> "a"
或者,更好的是,使用

后者说明了为什么
chr
不是变量名的最佳选择

下一个

现在我将缩进返回值,以强调我们正在第二次调用
permutation
<代码>置换的参数为:

  string #=> "b"
现在当我们执行:

  return [string] if string.size < 2
  #=> return ["b"] if "b".size < 2
result << ("b"[0..0] + "a" + "b"[0..-1])
  #=> result << ("b" + "a" + "b")
  #=> result << "bab"
与前面计算的
chr=>“a”一起使用。下一步:

result = []

for perm in perms
  for i in (0..perm.size)
    result << (perm[0..i] + chr + perm[i..-1])
  end
end
即:

for i in (0..1)
  result << ("b"[0..i] + "a" + "b"[i..-1])
end
i=>1
时:

result << ("b"[0..1] + "a" + "b"[1..-1])
  #=> result << ("b" + "a" + "")
  #=> result << "ba"
这显然不是你想要的

您需要做的是将双
for
循环更改为:

for perm in perms
  result << chr + perm
  for i in (1..perm.size-1)
    result << (perm[0..i-1] + chr + perm[i..-1])
  end
  result << perm + chr
end
让我们试试看:

permutation("ab")
  #=> ["ab", "ba"]
permutation("abc")
  #=> ["abc", "bac", "bca", "acb", "cab", "cba"]
permutation("abcd")
  #=> ["abcd", "bacd", "bcad", "bcda", "acbd", "cabd",
  #    "cbad", "cbda", "acdb", "cadb", "cdab", "cdba",
  #    "abdc", "badc", "bdac", "bdca", "adbc", "dabc",
  #    "dbac", "dbca", "adcb", "dacb", "dcab", "dcba"]

Eki,照片中你是哪一位?

谢谢你的帮助。但正如我提到的,我知道数组置换,我在文章中提到了这一点。我只是想找出我的代码出了什么问题。哇,伙计,真是太有用了。这正是我试图调试的:)非常感谢兄弟。我是中间的人:“我的GF和我最好的朋友在我身边:”欢呼MaestAkExcel是一个美丽的地方,只是因为有美丽的人喜欢你。答案就像一首诗。。。谢谢
for i in (0.."b".size)
  result << ("b"[0..i] + "a" + "b"[i..-1])
end
for i in (0..1)
  result << ("b"[0..i] + "a" + "b"[i..-1])
end
result << ("b"[0..0] + "a" + "b"[0..-1])
  #=> result << ("b" + "a" + "b")
  #=> result << "bab"
result << ("b"[0..1] + "a" + "b"[1..-1])
  #=> result << ("b" + "a" + "")
  #=> result << "ba"
result => ["bab" + "ba"]
for perm in perms
  result << chr + perm
  for i in (1..perm.size-1)
    result << (perm[0..i-1] + chr + perm[i..-1])
  end
  result << perm + chr
end
for perm in perms
  for i in (0..perm.size)
    result << perm.dup.insert(i,chr)
  end
end
perms.each_with_object([]) do |perm, result|
  (0..perm.size).each { |i| result << perm.dup.insert(i,chr) }
end
def permutation(string)
  return [string] if string.size < 2
  ch = string[0]
  permutation(string[1..-1]).each_with_object([]) do |perm, result|
    (0..perm.size).each { |i| result << perm.dup.insert(i,ch) }
  end
end
permutation("ab")
  #=> ["ab", "ba"]
permutation("abc")
  #=> ["abc", "bac", "bca", "acb", "cab", "cba"]
permutation("abcd")
  #=> ["abcd", "bacd", "bcad", "bcda", "acbd", "cabd",
  #    "cbad", "cbda", "acdb", "cadb", "cdab", "cdba",
  #    "abdc", "badc", "bdac", "bdca", "adbc", "dabc",
  #    "dbac", "dbca", "adcb", "dacb", "dcab", "dcba"]