我正在创建一个字符串中的排列和唯一字母数组,只是按字母顺序排序并找到集合中的中间元素。
def middle_permutation(string)
length = string.length
permutation_set = string.split("").permutation(length).to_a.map{|item| item.join}.sort
permutation_set.length.even? ? permutation_set[(permutation_set.length)/2-1] : permutation_set[(permutation_set.length/2)+1]
end
例如:
middle_permutation("zxcvbnmasd") should equal "mzxvsndcba"
即使对于小字符串(N> = 10),计算也需要很长时间才能完成,而且我可以忘记任何双重字符串;有更快的方法吗?
答案 0 :(得分:1)
我假设这些字母是唯一的,就像OP的问题一样。
答案 1 :(得分:1)
下面的方法直接返回所需的排列,而不迭代排列。
提问者声明该字符串不包含重复的字母,这是此方法的要求。我假设字符串的字符已排序。如果不是,则创建排序字符串将是第一步:
str = "ebadc".chars.sort.join
#=> "abcde"
<强>代码强>
def mid_perm(str)
return mid_perm_even_length_strings(str) if str.size.even?
first_char_index = str.size/2
str[first_char_index] << mid_perm_even_length_strings(str[0,first_char_index] +
str[first_char_index+1..-1])
end
def mid_perm_even_length_strings(str)
first_char_index = str.size/2-1
str[first_char_index] + (str[0,first_char_index] + str[first_char_index+1..-1]).reverse
end
<强>实施例强>
mid_perm 'abcd'
#=> "bdca"
mid_perm 'abcde'
#=> "cbeda"
mid_perm 'abcdefghijklmnopqrstuvwxyz'
#=> "mzyxwvutsrqponlkjihgfedcba"
<强>解释强>
让我们首先定义一个生成字符串字母排列的方法。
def perms(str)
str.chars.permutation(str.size).map(&:join)
end
包含偶数个字符的字符串
考虑
a = perms "abcd"
#=> ["abcd", "abdc", "acbd", "acdb", "adbc", "adcb",
# "bacd", "badc", "bcad", "bcda", "bdac", "bdca",
# "cabd", "cadb", "cbad", "cbda", "cdab", "cdba",
# "dabc", "dacb", "dbac", "dbca", "dcab", "dcba"]
a
包含4! #=> 4*3*2 => 24
个元素,4
是字符串的长度。
请注意,由于perms
'参数中的字符已排序,因此返回的数组也按 1 排序。
a == a.sort #=>true
作为a.size #=> 24
,“中间”元素为a[11] #=> "bdca"
或a[12] #=> "cabd"
(其中11 = (24-1)/2
和12 = 24/2
),具体取决于我们想要舍入的方式。这个问题规定,对于偶数长度的字符串,我们要向下舍入,这样就是"bdca"
。
现在让我们将a
切成str.size
个相等的数组,每个数组包含a.size/str.size #=> 24/4 => 6
个元素:
b = a.each_slice(a.size/str.size).to_a
#=> [["abcd", "abdc", "acbd", "acdb", "adbc", "adcb"],
# ["bacd", "badc", "bcad", "bcda", "bdac", "bdca"],
# ["cabd", "cadb", "cbad", "cbda", "cdab", "cdba"],
# ["dabc", "dacb", "dbac", "dbca", "dcab", "dcba"]]
因此,所需的元素是
b[(a.size/str.size-1)/2-1][-1]
#=> "bdca"
此值可以更直接地计算如下。
first_char_index = str.size/2-1
#=> 1
first_char = str[first_char_index]
#=> "b"
remaining_chars = (str[0,first_char_index] + str[first_char_index+1..-1]).reverse
#=> "dca"
first_char + remaining_chars
#=> "bdca"
相同的逻辑适用于具有偶数个字符的所有字符串。因此,我们可以编写上面代码部分中显示的方法mid_perm_even_length_strings
。
例如(对于12个字符的字符串)
mid_perm_even_length_strings 'abcdefghijkl'
#=> "flkjihgedcba"
包含奇数个字符的字符串
现在考虑
str = "abcde"
a = perms str
#=> ["abcde", "abced", "abdce", "abdec", "abecd", "abedc",
# "acbde", "acbed", "acdbe", "acdeb", "acebd", "acedb",
# "adbce", "adbec", "adcbe", "adceb", "adebc", "adecb",
# "aebcd", "aebdc", "aecbd", "aecdb", "aedbc", "aedcb",
# "bacde", "baced", "badce", "badec", "baecd",..., "bedca",
# "cabde", "cabed", "cadbe", "cadeb", "caebd", "caedb",
# "cbade", "cbaed", "cbdae", "cbdea", "cbead", "cbeda",
# "cdabe", "cdaeb", "cdbae", "cdbea", "cdeab", "cdeba",
# "ceabd", "ceadb", "cebad", "cebda", "cedab", "cedba",
# "dabce", "dabec", "dacbe", "daceb", "daebc",..., "decba",
# "eabcd", "eabdc", "eacbd", "eacdb", "eadbc",..., "edcba"]
此处排列包含5! #=> 100
个5
20
个a.each_cons(2).all? { |s1,s2| s1 < s2 } #=> true
个元素。 (再次,a
。)
str[str.size/2] #=> "c"
的中间元素显然是以
b = a.each_slice(a.size/str.size).to_a[str.size/2]
#=> ["cabde", "cabed", "cadbe", "cadeb", "caebd", "caedb",
# "cbade", "cbaed", "cbdae", "cbdea", "cbead", "cbeda",
# "cdabe", "cdaeb", "cdbae", "cdbea", "cdeab", "cdeba",
# "ceabd", "ceadb", "cebad", "cebda", "cedab", "cedba"]
该块将是数组
'c'
这将是["abde", "abed", "adbe", "adeb", "aebd", "aedb",
"bade", "baed", "bdae", "bdea", "bead", "beda",
"dabe", "daeb", "dbae", "dbea", "deab", "deba",
"eabd", "eadb", "ebad", "ebda", "edab", "edba"]
加上数组的中间元素
"abde"
该数组仅仅是字符串mid_perm_even_length_strings 'abde'
#=> "beda"
的排列。由于该字符串包含偶数字符,因此其中间元素为
"abcde"
因此,'c' + 'abde'
#=> "cabde"
字母排列的中间元素是
.sort
这显然适用于包含奇数个字符的所有字符串。
1。 Array#permutation的文档指出,“实现不能保证排列的顺序。”因此,我们可能需要将perms
添加到document.getElementById("element")
的操作行的末尾,但是使用Ruby v2.4(我怀疑,早期版本),实际上这里没有必要
答案 2 :(得分:0)
我能够像这样压缩它:
def middle_permutation(string)
list = string.chars.permutation.map(&:join).sort
list[list.length / 2 - (list.length.even? ? 1 : 0)]
end
哪个收益率:
middle_permutation('zxcvbnmasd')
# => "mzxvsndcba"
答案 3 :(得分:0)
事实证明,有两条曲目,奇数字符串甚至字符串。
对于奇数字符串,按顺序取出排序数组的中间字符元素和前面的元素。当你这样做时,你有两个剩余的阵列,左右一个,按字母顺序排序。您可以使用最后一个元素从右侧数组的元素开始,然后对左侧的元素执行相同操作。
对于偶数字符串,请执行相同但仅在第一步中使用一个字符:(N / 2)元素。
这是我的解决方案:
def middle_permutation(string)
string_array = string.chars.sort
mid_string = []
length = string.length
if length.even?
mid_string << string_array[length/2-1]
string_array.delete_at(length/2-1)
(mid_string << string_array.reverse).flatten.join
else
mid_string << string_array[(length/2)-1..length/2].reverse
string_array.slice!((length/2)-1, 2)
(mid_string << string_array.reverse).flatten.join
end
end
答案 4 :(得分:0)
您无需生成所有排列。只需查找排列的总数为PN = N!
,其中N是字符串(不同字符)长度,并按其编号仅计算所需的PN/2-th
排列 - 例如,使用this approach
public static int[] perm(int n, int k)
{
int i, ind, m=k;
int[] permuted = new int[n];
int[] elems = new int[n];
for(i=0;i<n;i++) elems[i]=i;
for(i=0;i<n;i++)
{
ind=m%(n-i);
m=m/(n-i);
permuted[i]=elems[ind];
elems[ind]=elems[n-i-1];
}
return permuted;
}