给出一个词,让我们使用“堆栈”,我想获得该词带有空格的所有变体。
例如,我要寻找一个像这样的数组:
[
'S tack',
'S t ack',
'S t a ck',
'S t a c k',
'Stac k',
'Sta c k',
'St a c k',
...
]
我没有任何代码可以显示,因为我无法解决此问题。我有一种感觉,我需要在每个字母处拆分单词,然后使用循环添加空格,然后将该单词添加到数组中,但是我不确定其背后的逻辑。我以为我需要使用模数%
,但是我也不是很清楚。
我正在为此使用Ruby,但鉴于这更多是一个逻辑问题,所以使用哪种语言并不重要。
答案 0 :(得分:5)
这是一个递归解决方案。
代码
def recurse(word)
return [word] if word.size == 1
first_char = word[0]
recurse(word[1..-1]).flat_map { |s| [first_char+s, first_char+' '+s] }
end
示例
arr = recurse 'Stack'
#=> ["Stack", "S tack", "St ack", "S t ack", "Sta ck", "S ta ck", "St a ck", "S t a ck",
# "Stac k", "S tac k", "St ac k", "S t ac k", "Sta c k", "S ta c k", "St a c k",
# "S t a c k"]
说明
此方法执行的步骤如下所示。请注意,每次调用recurse
时,打印的行都会缩进4个空格。
INDENT = 4
@off = 0
def s
' '*@off
end
def indent
@off += INDENT
end
def undent
@off -= INDENT
end
def recurse(word)
puts "#{s}Entering recurse(\"#{word}\")"
puts "#{s}Returning [\"#{word}\"] as \"#{word}\".size == 1" if word.size == 1
return [word] if word.size == 1
puts "#{s}Calling recurse(\"#{word[1..-1]}\")"
indent
a1 = recurse(word[1..-1])
undent
puts "#{s}recurse(\"#{word[1..-1]}\") returned a1 = #{a1}"
first_char = word[0]
puts "#{s}first_char = \"#{first_char}\""
a2 = a1.flat_map { |s| [first_char+s, first_char+' '+s] }
puts "#{s}Returning a1.flat_map { |s| first_char+s, first_char + ' ' + s] } = "
puts "#{s} #{a2}"
a2
end
recurse("dogs")
#=> ["dogs", "d ogs", "do gs", "d o gs", "dog s", "d og s", "do g s", "d o g s"]
打印
Entering recurse("dogs")
Calling recurse("ogs")
Entering recurse("ogs")
Calling recurse("gs")
Entering recurse("gs")
Calling recurse("s")
Entering recurse("s")
Returning ["s"] as "s".size == 1
recurse("s") returned a1 = ["s"]
first_char = "g"
Returning a1.flat_map { |s| first_char+s, first_char + ' ' + s] } =
["gs", "g s"]
recurse("gs") returned a1 = ["gs", "g s"]
first_char = "o"
Returning a1.flat_map { |s| first_char+s, first_char + ' ' + s] } =
["ogs", "o gs", "og s", "o g s"]
recurse("ogs") returned a1 = ["ogs", "o gs", "og s", "o g s"]
first_char = "d"
Returning a1.flat_map { |s| first_char+s, first_char + ' ' + s] } =
["dogs", "d ogs", "do gs", "d o gs", "dog s", "d og s", "do g s", "d o g s"]
@Marcin的答案的变化
word = 'Stack'
word_chars = word.chars
last_idx = word.size-1
(0..2**last_idx-1).map do |n|
n.bit_length.times.with_object(word_chars.dup) do |i,arr|
c = arr[last_idx-i]
arr[last_idx-i] = n[i] == 1 ? (' '+c) : c
end.join
end
#=> ["Stack", "Stac k", "Sta ck", "Sta c k", "St ack", "St ac k", "St a ck",
# "St a c k", "S tack", "S tac k", "S ta ck", "S ta c k", "S t ack", "S t ac k",
# "S t a ck", "S t a c k"]
请参见Integer#bit_length和Integer#[]。
通过检查n
的位,我们可以将(0..2**last_idx-1)
范围内的每个数字n
映射到所需数组的一个元素。具体来说,如果第i
个有效位是1
,则字符word[word.size-1-i]
前面要加一个空格;如果是0
,则该字符将不会以空格开头。
对于word = 'Stack'
,last_idx = 'Stack'.size-1 #=> 4
,因此范围是0..2**4-1 #=> 0..15
。这些数字对应于二进制数字0, 0b1, 0b10, 0b11, 0b110,...0b1111
。此范围内的一个数字是11
,其二进制表示形式由11.to_s(2) #=> "1011"
或0b1011
给出。由于第三最低有效位是0
,"a"
中的"Stack"
将保持不变,但是"t"
,"c"
和"k"
将分别映射到" t"
," c"
和" k"
(因为它们对应于1
中的0b1011
),产生字符串["S", " t", "a", " c", " k"].join #=> => "S ta c k"
。
请注意,此技术多少等效于使用方法Array#combination。
答案 1 :(得分:2)
9
产生
def combine_string_with(s, delimiter = " ")
combinations = (1..s.size - 1).flat_map { |n| (1..s.size - 1).to_a.combination(n).to_a }
combinations.map do |arr|
arr.reverse.each_with_object(s.dup) do |i, string|
string.insert(i, delimiter)
end
end
end
combine_string_with("Stack")
["S tack",
"St ack",
"Sta ck",
"Stac k",
"S t ack",
"S ta ck",
"S tac k",
"St a ck",
"St ac k",
"Sta c k",
"S t a ck",
"S t ac k",
"S ta c k",
"St a c k",
"S t a c k"]
是所有要放置定界符的索引的数组,即
combinations
在迭代组合时调用[[1], [2], [3], [4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]]
,以便从末尾插入定界符,因此索引在向后移动时将保持匹配。
答案 2 :(得分:2)
关注JörgW Mittag的评论:
'Stack'.
split(//).
map { |l| [l, "#{l} "] }.
reduce(&:product).
map(&:join)
答案 3 :(得分:0)
其他使用索引的选项,一个衬里:
string = 'Stack'
(1..string.size).map.with_object([]) { |n, res| (1..string.size-1).to_a.combination(n).map { |idxs| idxs.reverse.each.with_object(string.dup) { |i, tmp| res << tmp.insert(i, ' ') } } }.uniq
#=> ["S tack", "St ack", "Sta ck", "Stac k", "S t ack", "S ta ck", "S tac k", "St a ck", "St ac k", "Sta c k", "S t a ck", "S t ac k", "S ta c k", "St a c k", "S t a c k"]