我遇到了这个问题。
通过放置空格打印所有可能的字符串。
我也遇到了这个解决方案。
var spacer = function (input) {
var result = '' ;
var inputArray = input.split('');
var length = inputArray.length;
var resultSize = Math.pow(2,length-1); // how this works
for(var i = 0 ; i< resultSize ; i++){
for(var j=0;j<length;j++){
result += inputArray[j];
if((i & (1<<j))>0){ // how this works
result += ' ' ;
}
}
result += '\n' ;
}
return result;
}
var main = function() {
var input = 'abcd' ;
var result = spacer(input);
console.log(result);
}
main();
我没有得到标记线的工作原理?
您能澄清一下使用的技术吗?这背后的基本逻辑是什么?我们可以在哪些方面使用它?
感谢。
答案 0 :(得分:2)
我们以字符串abcd
为例。
有三个可以放置空间的地方:
因此,一般来说,如果字符串的长度为length
,则您有length - 1
个空格位置。
假设每个这样的地方用二进制数字中的单独数字表示。当我们不在那里放置空间时,这个数字是0,当我们这样做时,这个数字是1。 E.g:
a b c d
0 0 0
表示我们不会放置任何空格 - abcd
0 0 1
意味着我们在&#34; c&#34;之间放置了空格。和&#34; d&#34;仅 - abc d
0 1 0
意味着我们在&#34; b&#34;之间放置了空格。和&#34; c&#34;仅 - ab cd
0 1 1
表示ab c d
1 0 0
表示a bcd
1 0 1
表示a bc d
1 1 0
表示a b cd
1 1 1
表示a b c d
将000
,001
,010
,...,111
从二进制转换为十进制将为我们提供值0
,1
,2
,...,7
。
有3个空格位置,我们有8个选项可以放置它们。它完全是2^3
或2^(length - 1)
。
因此,我们需要迭代0
(包含)和2^(length - 1)
之间的所有数字(不包括)。
您提供的代码中的条件(i & (1 << j)) > 0
只检查位置j
(从结尾开始,从0开始)的数字是否为0
(我们不需要插入空格)或1
(并且应添加空格)。
让我们以值6
(二进制为110
)为例。
(6 & (1 << 0)) = 110 & 001 = 000 = 0
(条件> 0
未达到)
(6 & (1 << 1)) = 110 & 010 = 010 = 2
(符合条件> 0
)
(6 & (1 << 2)) = 110 & 100 = 100 = 4
(符合条件> 0
)
答案 1 :(得分:0)
每两个字符之间有两种可能性:是否有空格。如果仅在字符之间允许空格,则4个字符的可能性数量为2 * 2 * 2或2 ^(长度 - 1)
答案 2 :(得分:0)
resultSize = Math.pow(2, length - 1)
表示在给定问题定义的情况下,有2 ^ n-1种方法可以打印字符串。至于为什么这样的解决方案的数量很容易理解,如果你从一个有2个字符的字符串开始并向上工作。所以假装你有字符串“ab”。有两种解决方案,你可以在a和b之间放一个空格,或者你不能在a和b之间放一个空格。让我们添加一个字符来获得“abc”。好吧,我们已经知道字符串“ab”有两种解决方案,所以我们需要通过在b和c之间放置空格的方式来乘以该解决方案。这是2,所以我们提供2 * 2解决方案。您可以将其扩展为n大小的字符串。这意味着解决方案的数量是2 * 2 * 2 * 2 * ... n - 1.或者换句话说2 ^ n-1。
下一部分有点棘手,但它是一种聪明的方法,可以确定在任何给定的解决方案中有多少空格和它们在哪里。按位&
取两个数字的每一位,比较它们,然后吐出一个新数字,如果两个数字的两个位都是1则每个位为1,如果位不是1,则为0 1.例如(二进制数):
01 & 01 = 01
10 & 01 = 00
或者更大的例子:
10010010 & 10100010 = 10000010
<<
运算符只是将所有位n移动到左边,其中n是右手表达式(乘以2 n次)。
例如:
1 << 1 = 2
2 << 1 = 4
2 << 2 = 8
1 << 4 = 8
现在回到你的代码。让我们分解if语句
if(i & (1 << j) > 0){ ... }
在英语中,这说,如果我们正在查看的解决方案的数字索引共享任何1位,其中1位移动了我们正在查看的字符的索引,那么在该字符之后放置一个空格。 Olexiy Sadovnikov的答案有一些很好的例子说明了一些迭代会是什么样子。
值得注意的是,这不是唯一的方法。您可以非常轻松地确定空间的最大数量是n - 1然后只是线性地找到其中包含0个空格的所有解,然后找到其中有1个空格的所有解,然后是2个空格.... n - 1个空格。虽然你发布的解决方案比这样做更快。当然,当你谈论指数复杂度的算法时,它最终无关紧要,因为大于大约60个字符的字符串将比你可能需要等待的时间更长,即使使用严格的2 ^ n算法也是如此。
回答这些技术如何在其他地方使用的问题。比特移位非常频繁地用于加密算法以及按位和比特。和|运算符。
答案 3 :(得分:0)
'''
The idea was to fix each character from the beginning and print space separated rest of the string.
Like for "ABCD":
A BCD # Fix A and print rest string
AB CD # Add B to previous value A and print rest of the string
ABC D # Add C to previous value AB and print rest of the string
Similarly we can add a space to produce all permutations.
Like:
In second step above we got "AB CD" by having "A" as prefix
So now we can get "A B CD" by having "A " as a prefix
'''
def printPermute(arr, s, app):
if len(arr) <= 1:
return
else:
print(app +''+arr[0:s] +' '+ arr[s:len(arr)])
prefix = app + ''+arr[0:s]
suffix = arr[s:len(arr)]
printPermute(suffix, 1, prefix)
printPermute(suffix, 1, prefix+' ') #Appending space
printPermute("ABCDE", 1, '') #Empty string
答案 4 :(得分:0)
使用 JavaScript
的简单解决方案String.prototype.splice = function(idx, rem, str) {
return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};
function printPattern(str, i, n){
if(i==n){
return;
}
var buff = str;
var j = str.length - n + i;
buff = str.splice(j,0," ");
console.log(buff);
printPattern(str, i+1, n);
printPattern(buff, i+1, n);
}
var str = "ABCD"
printPattern(str, 1, str.length);
console.log(str);
答案 5 :(得分:-1)
.pow
是来自Math
的方法,代表“权力”。它需要两个参数:基数(此处为2
)和指数。请阅读here了解详情。
&
是按位AND运算符,它采用数字的两个二进制表示并执行逻辑AND,这里是bitwise operators上的一个线程
Math.pow(2,length-1)
为我们提供了可能的字符串数量?我记得在去年的数学课上练习,但我会尝试不加总结来解释它。
基本上我们想通过在字母之间添加一个空格或不添加空格来确定可以创建的字符串数。您的初始字符串包含n
个字母。原因如下:
从左边开始或每个字母后面的单词有两个选择
1 - 放一个空格
2 - 不要放空格
您必须在两个选项之间选择n-1
次。
这意味着您将有2^(n-1)
种可能的解决方案。