簡體   English   中英

用分隔符找到最大的子數組長度

[英]Find the largest subarray length with delimiter

我正在嘗試解決這個問題:

給定兩個參數:數組a和整數i ,找到所有元素之和<= i的最大數組長度。

例如,有以下數組: [3, 1, 2, 1]i = 4 ,所有<= i的組合是: [3], [1], [2], [3, 1], [1, 2], [1, 2, 1] 最大的子數組是[1, 2, 1] ,所以函數的返回值應該是3 (數組長度)。

解決這個問題的有效方法是什么?

到目前為止,這是我的算法,但我知道我遺漏了一些東西:

function sumArray(a) {
    return a.reduce((a, b) => a + b, 0)
}

function maxLength(a, i) {
   let max = 0
   let array = [a[0]]
   a.splice(1, a.length).forEach(number => {
     array.push(number)
     if (sumArray(array) <= k) max = array.length
     else array.splice(array.indexOf(Math.max.apply(null, array)), 1)
   })
   return max
}

這是我將如何做到的。

首先,我們將通過只從原始元素中取出最小的元素來獲得最長的子數組,因為這樣一來,隨着我們的進行,總和將盡可能地最小。 所以:

 const original = [3, 1, 2, 1]; const maxsum = 4; // To make sure we take only the smallest, let's just // sort the array straight away. That way the smallest // element will always be the first. // The .slice call is to make a copy, so we don't change // the original: const sorted = original.slice().sort(); // Here's your sum function. Looks legit. function sumArray(a) { return a.reduce((a, b) => a + b, 0) } // Now take items from the front of the sorted array and // put them in the new array until either the original is // empty or the max is reached. let subarray = []; while (sorted.length) { // Get the next smallest element. It's always the // first one because of the sort. const smallest = sorted.shift(); // If the sum of what we have plus this new element // is bigger than the max, our work is done: if (sumArray(subarray) + smallest > maxsum) break; // Otherwise, add it to our sub array and continue. subarray.push(smallest) } // Once that loop has run, either we ran out of elements, // or we hit the max. Either way, our job is done. console.log("Original array:", original); console.log("Maximal subset:", subarray); console.log("Maximal subset length:", subarray.length);

最后,如果你想變得有趣,你甚至可以通過一個.reduce調用來做到這一點:

 const original = [3, 1, 2, 1]; const maxsum = 4; const maximalSubset = original.slice().sort().reduce((subset, current) => { if (subset.reduce((s, c) => s + c, 0) + current <= maxsum) subset.push(current); return subset; }, []); console.log("Orignal:", original); console.log("Maximal subset:", maximalSubset); console.log("Maximal subset length:", maximalSubset.length);

雖然較短,但第二個片段的缺點是我們必須在獲得結果之前迭代整個數組,而第一個片段將在達到最大值后停止。

編輯:

事實證明,子數組需要是原始的連續片段,因此更改原始的順序將不起作用,因為我們需要確保結果是原始的連續切片。

為此,只需檢查數組的每個子切片,並保留最好的一個:

 let original = [74,659,931,273,545,879,924,710,441,166,493,43,988,504,328,730,841,613,304,170,710,158,561,934,100,279,817,336,98,827,513,268,811,634,980,150,580,822,968,673,394,337,486,746,229,92,195,358,2,154,709,945,669,491,125,197,531,904,723,667,550]; const maxsum = 22337; function arraySum(arr) { return arr.reduce((p, c) => p + c, 0); } // Double for loop will do the trick. let bestSoFar = []; for (let i = 0; i < original.length; i++) { for (let j = i+1; j < original.length; j++) { if (ji > bestSoFar.length && arraySum(original.slice(i, j)) < maxsum) { bestSoFar = original.slice(i, j); } } } console.log("Longest continuous subarray is:", bestSoFar.length);

蠻力方法可能是解決此問題的最佳方法。 從每個條目開始,看看在達到總和> i之前你能走多遠,如果它比你迄今為止看到的最好的更好,就保存它。 我在下面提供了一個示例 Java 解決方案,我還沒有實際運行它,所以我的一兩個索引可能會關閉,但我認為您可以了解要點。 運行時間是 O(n^2),內存是 O(n)(兩者都發生在,例如,#getMaxSubArray(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 1000000))

private int[] getMaxSubArray(int[] a, int i) {
  int minIndex = 0;
  int maxIndex = -1;
  for (int j = 0; j < a.length; j+=1) {
    if (a[j] > i) {
      continue;
    }

    int sum = a[j];
    for (int k = j + 1; k < a.length; k++) {
      if (sum + a[k] > i) {
        if ((k - 1) - j > maxIndex - minIndex) {
          maxIndex = k - 1;
          minIndex = j;
        }
        break;
      }
      sum += a[k];
    }
  }

  if (maxIndex - minIndex < 0) {
    return null;
  }
  int[] result = new int[maxIndex - minIndex + 1];
  for (int p = minIndex; p <= maxIndex; p += 1) {
    result[p - minIndex] = a[p];
  }
  return result;
}

這是我的解決方案。 它將返回子數組的最大長度。 可以請你看一下嗎,伙計們?

function maxLength(a, k) {
const sortedArray = a.sort((i,j) => i - j);
let sum = 0;
let length = 0;
const subArray = [];
for (let i=0; i < sortedArray.length; i++) {
   sum = sum + sortedArray[i];
   if (sum <= k) {
      length++;
      subArray.push(sortedArray[i]);
   } else {
       return length;
   }
}
return length;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM