[英]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.