使用javascript在o(n)时间1D数组中查找所有子数组

时间:2016-09-16 06:45:20

标签: javascript arrays algorithm kadanes-algorithm

我想在javascript中有效地收集所有子数组以进一步计算。我不确定这是可能的,但似乎对于一个子阵列和kadane的公式是o(n),它比其他方法更有效。但我不确定我是如何在每一步都存储阵列的。

与此quora question类似,对我来说伪代码还不够。感谢您进一步细分。

另一个meta link

[3,3,9,9,5]

的一个例子
[3], [9], [5], [9, 5], [9, 3], [9, 9], [3, 3],
[3, 9, 9], [3, 3, 9], [9, 9, 5], [3, 3, 9, 9],
[3, 9, 9, 5], [3, 3, 9, 9, 5]

3 个答案:

答案 0 :(得分:1)

我之前做过一项工作来计算氨基酸总分子量的所有组合。如果忽略空的那个,你应该有2 ^ n - 1个子阵列。所以这里没有O(n)。我有两种方法,如二进制和递归。



function getSubArrays(arr){
  var len = arr.length,
     subs = Array(Math.pow(2,len)).fill();
  return subs.map((_,i) => { var j = -1,
                                 k = i,
                               res = [];
                             while (++j < len ) {
                               k & 1 && res.push(arr[j]);
                               k = k >> 1;
                             }
                             return res;
                           }).slice(1);
}

console.log(JSON.stringify(getSubArrays([1,2,3,4,5])));
&#13;
&#13;
&#13;

&#13;
&#13;
function getSubArrays(arr){
  if (arr.length === 1) return [arr];
  else {
  	subarr = getSubArrays(arr.slice(1));
  	return subarr.concat(subarr.map(e => e.concat(arr[0])), [[arr[0]]]);
  }
}

console.log(JSON.stringify(getSubArrays([1,2,3,4,5])));
&#13;
&#13;
&#13;

我无法设法获得超过23个项目的数组的子数组。 这是表演。为了安全起见,我尝试使用22个项目,首先使用递归,然后使用二进制路径。

&#13;
&#13;
function getSubArrays(arr){
  if (arr.length === 1) return [arr];
  else {
  	subarr = getSubArrays(arr.slice(1));
  	return subarr.concat(subarr.map(e => e.concat(arr[0])), [[arr[0]]]);
  }
}


var aminos = Array(22).fill().map((_,i) => i+1),
   subarrs = [],
        ps = 0,
        pe = 0;
ps = performance.now();
subarrs = getSubArrays(aminos);
pe = performance.now();
console.log("recursive route took: " + (pe-ps) + "msec to produce " + subarrs.length + " sub arrays");
&#13;
&#13;
&#13;

&#13;
&#13;
function getSubArrays(arr){
  var len = arr.length,
     subs = Array(Math.pow(2,len)).fill();
  return subs.map((_,i) => { var j = -1,
                                 k = i,
                               res = [];
                             while (++j < len ) {
                               k & 1 && res.push(arr[j]);
                               k = k >> 1;
                             }
                             return res;
                           }).slice(1);
}

var aminos = Array(22).fill().map((_,i) => i+1),
   subarrs = [],
        ps = 0,
        pe = 0;
ps = performance.now();
subarrs = getSubArrays(aminos);
pe = performance.now();
console.log("binary route took: " + (pe-ps) + "msec to produce " + subarrs.length + " sub arrays");
&#13;
&#13;
&#13;

答案 1 :(得分:1)

这很简单:https://jsfiddle.net/j1LuvxLq/

您所做的只是迭代可能的长度和起点,然后打印出子集。复杂度为O(n²),其中n是原始数组的长度。无法改进它,因为这是有多少子集的顺序。

var set = [3, 3, 9, 9, 5].join('')

var set_length = set.length

var subsets = []

for (var length_of_subset = 1; length_of_subset <= set_length; length_of_subset++) {
    for (var start_of_subset = 0; start_of_subset <= set_length - length_of_subset; start_of_subset++) {
        var current_subset = set.substring(start_of_subset, start_of_subset + length_of_subset)
        if(subsets.indexOf(current_subset) == -1) {
            subsets.push(current_subset.split(''))
        }
    }
}

// print the subsets out
for (s in subsets) {
    $('body').append(subsets[s].join(', ') + '<br>')
}

替代方案,可能更好的解决方案是使用动态编程。从3开始,删除最后一个元素或添加下一个元素。请在此处查看:https://jsfiddle.net/p82fcs4m/

var set = [3, 3, 9, 9, 5].join('')
var subsets = []

take(set[0], set.substring(1))

function take(chosen, left) {

    if(subsets.indexOf(chosen) != -1) {
        return
    }

    subsets.push(chosen)

    if (chosen.length > 1) {
        take(chosen.substring(1), left)
    }

    if (left.length > 0) {
        take(chosen.concat(left[0]), left.substring(1))
    }
}

$('body').append(subsets.join('<br>'))

答案 2 :(得分:0)

我相信使用Array.slice是最干净的方法,不是吗?

function getSubArrays(arr) {
    const subArrays = [];
    for (var i = 0; i < arr.length; i++) {
        for (var j = i; j < arr.length; j++) {
            subArrays.push(arr.slice(i, j + 1));
        }
    }
    return subArrays;
}