返回满足条件的数组元素的数量

时间:2018-06-27 15:45:57

标签: javascript algorithm

我试图让我的函数返回最大数组索引数,该数组索引按顺序加在一起等于0-不容易解释,但下面是一些带注释的测试示例:

longestSlice([-1, -1, 1, -1, 1, 0, 1, -1, -1]); // should return 7 (slice starts at 2nd position)
longestSlice([1, 1, -1, -1, -1, -1, -1, 1, 1]); // should return 4 (both the first four elements and the last four elements)
longestSlice([-1, -1, -1, -1, 1, 0, 1, -1, -1]); // should return 5 (slice starts at 4th position)

我的函数正确返回前两个测试,但不返回第三个测试。我认为我的逻辑是错误的,但我无法终生想出解决方案。如何做到这一点?我尝试过:

// if a[i] + a[i+1] = 0, count++, then if a[i-1] + a[i+2] = 0, count++ etc - won't work
// if a[i] + a[i+1] + a[i+2] + ... + a[i+n/2] > n (or -n) - won't work
// tests considering: count no of -1, 0 and 1 instances

此外,有人可以解释一下如何轻松实现此类情况的解决方案,因为它看起来比看起来更难,而且我对javascript还是比较陌生。感谢您的任何建议。

function longestSlice(arr) {

	var N = arr.length;
	var totalSum = 0, sliceLength = 0;
	var slices = [];

	if (N < 1) {
		throw new RangeError('Bad Input - Function Aborted');
	} else {
		// continue...
		for (i = 0; i < N; i++) {
			totalSum += arr[i];
			sliceLength++;
			console.log('totalSum: ' + totalSum + '\nsliceLength: ' + sliceLength);
			
			if (totalSum === 0) {
				slices.push(sliceLength);
				sliceLength = 0;
				console.log('sliceLength reset to: ' + sliceLength);
			}
		}
		return slices;
	}
}

4 个答案:

答案 0 :(得分:1)

基本上,您将需要一个双循环。

外部循环将从第一个数组元素开始。

然后,子循环从此起点循环到结束,并保持一个总和,每当该总和等于0时,它都会检查其是否最大并存储是否为最大。

下面的例子。

def fixed_relationship_sweep(input_params, together):
    """
    Inputs
    ------
    input_params: {0:[x1, x2], 1:[x3, x4], 2:[y1, y2], 3:[y3, y4]]}
    dictionary mapping qubits to parameter lists to iterate through
    together: [[0, 1], [2, 3]]
    list of qubit lists that specify which qubit parameters to sweep with a fixed relationship

    Output
    ------
    fixed_rel_sweep: [{trial1}, {trial2}, ...{trialn}] where qubits labelled as "together" are
    swept with fixed 1-1 relationship, ie, above produces:
    [{0:x1, 1:x3, 2:y1, 3:y3}, {0:x1, 1:x3, 2:y2, 3:y4}, {0:x2, 1:x4, 2:y1, 3:y3},
    {0:x2, 1:x4, 2:y2, 3:y4}] 
    """
    qsorcs = []
    params = []
    #index representation of params, as cartesian product must respect fixed positions
    #of arguments and not their values, ie [x1, x3] vary together in example
    tempidxrep = []
    for key, value in input_params.items():
        qsorcs.append(key)
        params.append(value)
        tempidxrep.append([i for i in range(len(value))])

    idxrep = []
    #remove redundancy in index representation governed by fixed relationships in together
    for fix_rel in together:
        idxrep.append(tempidxrep[fix_rel[0]])

    #sweep combinations via carteisan product
    idxcombos = itertools.product(*idxrep)

    #reconstruct actual parameter combinations
    param_combos = []
    for idxcombo in idxcombos:
        trial = {qsorcs[j]: params[j][idxcombo[i]] for i in range(len(idxcombo)) for j in together[i]}
        param_combos.append(trial)

    return param_combos

答案 1 :(得分:1)

之前已经实现了类似的算法。可以递归完成

function longestSlice(arr, acc=0) {

    let N = arr.length;

    if (N == 0) {
        return acc
    } else {
        let sum = 0
        let bestSoFar = 0;
        for (let i =0; i < N; i++) {
            sum += arr[i]
            if (sum ==0) {
                bestSoFar = i+1;
            }
        }

        return  longestSlice(arr.slice(1,N), Math.max(bestSoFar, acc));
    }
}


longestSlice([-1, -1, -1, -1, 1, 0, 1, -1, -1]);    // returns 5

答案 2 :(得分:1)

function longestSlice(arr) {
  let longestSliceLength = 0
  for (let i = 0; i < arr.length - longestSliceLength; i++) {
    let sum = 0
    let currentSliceLength = 0
    for (let j = i; j < arr.length; j++) {
      currentSliceLength++;
      sum += arr[j]
      if (!sum && longestSliceLength < currentSliceLength) {
        longestSliceLength = currentSliceLength
      }
    }
  }
  return longestSliceLength
}
  

有人可以解释如何轻松解决此类情况

嗯,我们需要一种算法来解决此问题,并且实际上没有任何时间/空间限制。我们该如何解决这个问题?最长子序列应小于序列本身(很明显,有限对象的一部分小于或等于对象大小)。然后,让我们尝试所有连续的子序列,从最大的子序列开始(从第一个元素开始,但是如果需要,我们可以从另一端开始)。添加数量,计算总和以及总和中已包含的元素数。当总和等于零时-我们有一个满足要求的子序列。如果它是我们到目前为止看到的最大长度,我们将保存它的长度。重复。希望这会有所帮助。

答案 3 :(得分:1)

好吧,让我们这样看吧:

假定我们有一个数组长度N,该数组的总和为X。现在...

如果X为零,则其N(数组的长度)是将总计为0的最大数字。

如果X不为零,则可能会有一些数字(假设为K个数字)加起来等于值X,结果长度应为N-K最大数总数为零的数。如果没有K (1<=K<=N)数量的数字0 (by sum),则该数组不能通过任何组合的总和产生零。

好吧,如果有点混乱,让我们举个例子。

假设一个长度为75的数组(因此,N在这里是75

现在,假设73个数字(特定组合)的最大和等于0(所以这里K73),而数组的总和是{ {1}}肯定是其其余15个数字的总和(以其他2个数字之和为73的组合)

因此,我们可以搜索总和值0的最小组合(它是整个数组总和,在此用0表示,而不是搜索总和的最长组合)在前面的语句中),我们可以简单地用15的输入减去并得到结果。在这里,我们可以

  1. 避免递归
  2. 避免生成长度不超过结果的组合(例如,长度不超过X, 找到长度length及其和的所有组合后退出)
  3. 重新使用最后组合的结果来生成下一个长度 组合
  4. 当我们发现总和为73(整个数组的总和)时退出 可能的最小组合

因此,算法的最后步骤:

  1. 第一步:2在阵列上
  2. 检查X是否为sum并返回sum的长度
  3. 如果0不为零,则从长度array的组合开始。对于 长度sum,由于长度1,我们可以避免计算1,因此 项目本身将是该组合(共1个)的sum值。所以 如果发现商品的价值为1,我们禁止休息, 返回sum 如果未找到X (the entire sum),则开始生成2个数字的所有组合并计算总和的过程。如果发现总和为<Inputs length - 1>,则可以中断并返回X。如果未找到所有长度为X且仍为N - 2的组合,我们可以传递长度为2的所有组合并生成长度为X的所有组合,然后{ {1}},依此类推。每当我们得到结果(总和等于2)时,我们都会中断并相应地返回(3或(4)。

现在,继续创建长度为X的组合

我们可以创建值的组合,但是由于值可以重复且难以管理,因此我们将创建N - 3的组合,并且我们可以随时在输入数组中查找值产生总和。

假设一个数组包含N - 4个元素,那么我们就可以拥有2, 3, 4...的组合

让我们生成索引并在下一次重新使用:

indexes

既然如此,我们将重新使用以前的组合,使用每个组合的最后一个索引,然后从该位置开始

避免重复的组合,并选择所有唯一的组合 它将始终推送增量索引,因此我们可以选择最后一个索引(它将是较大的索引)并直接进行处理,而不是在组合中搜索元素,并避免该组合(如果该元素存在)。这种情况永远不会发生。例如,您拥有索引4的组合,而您正在处理1, 2, 3 and 4,则无需处理。您可以立即从let array = [-15, 10, 5, 13], cm; function comboNext(a, L) { let res = [], i; a.forEach(p => { let last = p[p.length - 1], i; for (i = last + 1; i < L; i++) {res.push(p.concat(i)); } }) return res; } //this is not part of algo, just to format properly //to display the combinations properly function format(c) { return c.map(n=>n.join('+')).join(',\n') } cm = array.map((v, i) => [i]); //just indexes for 1 length combos console.log(format(cm) + ' => All of length 1'); cm = comboNext(cm, array.length); console.log(format(cm) + ' => All of length 2'); cm = comboNext(cm, array.length); console.log(format(cm) + ' => All of length 3'); cm = comboNext(cm, array.length); console.log(format(cm) + ' => All of length 4');开始处理。同样,如果您有一组索引0 1, 2,则必须从2开始处理,不要担心3的其他组合,它们会像1,2, 5一样出现,因此当处理6会相应地生成3,42,3,4。这样您就不会错过任何东西。

现在,让我们执行一下。而不是返回原始的组合数组,我们将返回一个带有5标志并且最后一次处理该组合的对象。我们将使用简单的2,3,4,5来随时执行2,3,4,6

success
请注意,我使用了2种不同的函数,一种用于创建长度为1的组合(因为这很简单,我们可以避免在那儿求和),另一种用于创建任何长度的组合并输入索引的最后一个长度组合。 p>