FOR MODERATOR:
这个被认为是重复的问题,并没有解决许多问题。
combinationsCount = 1 << listSize
一个在循环中转动迭代器'i'
到一个位向量,可以针对特定的'j'进行测试来确定
如果它应该包含在要测试的总和中。我认为,这是解决硬币变化问题的一种解决方案。据我所知,代码是有效的,但是我不明白最后一次检查是怎么回事:
if (i & (1 << j)) {
combinationSum += arr[j];
}
适用于此算法(见下文)。我遇到了一个教程。我非常感谢有关代码部分如何工作的任何解释。
更新:
要清楚,我理解运算符正在做的 WHAT ,即位移和逐位加法。我想知道的是它们如何在算法中运作。
possibleCombinationSumN(arr, n) {
if (arr.indexOf(n) >= 0) {
return true;
}
if (arr[0] > n) {
return false;
}
if (arr[arr.length - 1] > n) {
arr.pop();
return possibleCombinationSumN(arr, n);
}
var listSize = arr.length, combinationsCount = (1 << listSize)
for (var i = 1; i < combinationsCount; i++) {
var combinationSum = 0;
for (var j = 0; j < listSize; j++) {
if (i & (1 << j)) {
combinationSum += arr[j];
}
}
if (n === combinationSum) {
return true;
}
}
return false;
};
答案 0 :(得分:2)
i
用作位向量(零和一行),用于打开或关闭相应数组值在总和中的参与。
例如,如果arr
有4个元素,则i
为11
时,其二进制表示为0b1011
;这表明我们应该总结arr[3] + arr[1] + arr[0]
,并省略arr[2]
。
现在 - 对于四元素数组,i
将从0
转到15
。为什么?由于1 << arr.length
是二进制0b10000
(0b1
向左移动了四个位置)或16
,因此我们循环到其下方。这给出了0b0000
和0b1111
之间的二进制值 - 即四个1和0的所有可能组合。如果我们总结相应的数组值,我们将测试所有可能的总和组合。
i & (1 << j)
测试j
位是1
。
说j
为3
,i
为上述11
(0b1011
)。 1 << j
是0b1000
; 0b1011 & 0b1000
是0b1000
,这是真实的。位于3
的位置为arr[3]
,而combinationSum
位于j
。
说2
是1 << j
。 0b10
是0b1011 & 0b100
; 0b0
是2
,这是假的。位置arr[2]
处为零; if __name__ == '__main__':
g = Gui()
g.start()
没有得到总结。