使用Ruby和递归查找所有可能的排列
我一直在尝试解决一个简单的测验问题,用Ruby和递归找到字符串的所有可能排列 我有以下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)
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"]