我正在处理一个问题,该问题需要作为子例程对此进行回答。我知道如何使用位操作从数组生成所有子序列,但是却很难生成偶数长度的子序列。
为方便起见,假设有一个数组A = [2, 5, 4, 2, 3, 1]
我想要所有长度相等的子序列,即长度2、4和6。
编辑1:1 <= N <= 1000,其中N是数组的大小。
答案 0 :(得分:0)
使用generator functions,您可以利用延迟执行来迭代所有偶数长的子数组,而无需在内存中保留整个子数组集合:
function * subarrays (array) {
for (let length = 1; length <= array.length; length++) {
for (let index = 0; index + length <= array.length; index++) {
yield array.slice(index, index + length);
}
}
}
const filter = predicate => function * (iterator) {
for (const value of iterator) {
if (predicate(value)) yield value;
}
};
const even = filter(subarray => subarray.length % 2 === 0);
for (const subarray of even(subarrays ([2, 5, 4, 2, 3, 1]))) {
console.log(subarray.join());
}
但是,如果您确实想要整个偶数长的子数组集合,则可以使用Array.from()
来消耗迭代器并填充子数组数组:
function * subarrays (array) {
for (let length = 1; length <= array.length; length++) {
for (let index = 0; index + length <= array.length; index++) {
yield array.slice(index, index + length);
}
}
}
const filter = predicate => function * (iterator) {
for (const value of iterator) {
if (predicate(value)) yield value;
}
};
const even = filter(subarray => subarray.length % 2 === 0);
const result = Array.from(even(subarrays([2, 5, 4, 2, 3, 1])));
console.log(JSON.stringify(result));
要迭代所有偶数长的子序列,最简单的方法之一是保留一个查找表,该表的值来自数组,filter()
。通过利用Uint32Array
:
function _increment (uint32Array) {
for (let index = 0; index < uint32Array.length; index++) {
// use unsigned integer overflow to
// perform carry in base 2**32 addition
if (++uint32Array[index]) return;
}
}
function * subsequences (array) {
const lut = new Uint32Array(Math.ceil(array.length / 32));
let subsequence;
while (true) {
yield subsequence = array.filter(
(_, index) => (lut[index >>> 5] >>> (index % 32)) & 1
);
if (subsequence.length === array.length) return;
_increment(lut);
}
}
const filter = predicate => function * (iterator) {
for (const value of iterator) {
if (predicate(value)) yield value;
}
};
const even = filter(({ length }) => (length > 0) && (length % 2 === 0));
for (const subsequence of even(subsequences([2, 5, 4, 2, 3, 1]))) {
console.log(subsequence.join());
}
答案 1 :(得分:0)
由于您已经知道如何生成所有子序列,因此只需删除最后一个元素并生成剩余数组的所有子序列,然后将最后一个元素以奇数长度附加到每个子序列即可。
容易证明这会生成所有偶数长度的子序列:
答案 2 :(得分:0)
#include <stdio.h>
#define N 4
const int A[] = { 2, 5, 4, 2, 3, 1, -1 };
int out[1000];
void gen(const int *p, int *pout) {
if(pout - out < N) {
while((*pout = *p++) > 0)
gen(p, pout + 1);
} else { // print output
for(const int *o = out; o < pout; o++)
printf("%d ", *o);
putchar('\n');
}
}
int main(int argc, char **argv) {
gen(A, out);
return 0;
}
答案 3 :(得分:0)
这是Python,它和伪代码一样好:
def even_subsequences(L):
# yield the empty subsequence
yield []
# iterate over subsequence starting points
for i in range(len(L)):
# subsequence end point is the starting point plus an even number
for j in range(i+2, len(L)+1, 2):
# slice the list
yield L[i:j]
>>> list(even_subsequences([1,2,3,4,5,6]))
[[],
[1, 2],
[1, 2, 3, 4],
[1, 2, 3, 4, 5, 6],
[2, 3],
[2, 3, 4, 5],
[3, 4],
[3, 4, 5, 6],
[4, 5],
[5, 6]]