给定长度为int
的{{1}}数组,将数组拆分为3个部分,并确保2个较小的部分尽可能大。
分裂规则:
n
和a
(0 <= a&lt; = b&lt; = n-1)预期输出是2个较小部分(它们的大小)的总和。
示例,给出了b
的数组和一些值。
解决方案计算n = 6
,a = 2
将数组拆分为3个部分:左侧部分的大小为b = 3
,中间部分为6 + 7 = 13
,右侧部分为8 + 9 = 17
。输出为4 + 5 = 9
(两个较小部分的总和)。
图形表示:
更多例子:
[6,8,3,5,7,2,4,6]应分为:
13 + 9 = 22
)6 + 8 = 14
)3 + 5 + 7 = 15
)输出为2 + 4 + 6 = 12
(2个较小部分的总和)
14 + 12 = 26
)9 + 12 + 4 = 25
)7 + 10 + 2 + 5 = 24
)输出为8 + 11 + 3 = 22
(2个较小部分的总和)
我的方法对于给定的测试用例不起作用:
22 + 24 = 46
答案 0 :(得分:3)
想到的基本想法:
b
的所有位置。
O(n)
的所有位置。
通过注意以下几点,可以优化b
:
a
,b
的最佳位置总是在a
的中间和开始时(特别是在最小化的位置)左和中间总和之间的差异)。b
的最佳位置无法向左移动b
向右移动(因为这样会减少左边的总和,减少目标总和)。a
循环,同时跟踪int arr[] = {9, 12, 4, 7, 10, 2, 5, 8, 11, 3};
int sum = 0;
for (int i: arr)
sum += i;
int a = 0;
int left = 0, mid = 0;
int best = 0;
for (int b = 0; b < arr.length; b++)
{
mid += arr[b];
// since this loop increases `a` with every iteration, and `a` never resets,
// it will not run more than O(n) times in total
while (a < b && Math.min(left + arr[a], mid - arr[a]) > Math.min(left, mid))
{
left += arr[a];
mid -= arr[a];
a++;
}
int right = sum - mid - left;
best = Math.max(best,
mid + left + right - Math.max(mid, Math.max(left, right)));
}
System.out.println(best);
,并在适当的时候增加它。这给了我们以下代码:
a b
6 7 | 8 9 | 4 5
L=13 M=17 R=9
您遇到的问题是当您遇到以下情况时:
M > Math.max(L, R)
Math.min(left + arr[a], mid - arr[a]) > Math.min(left, mid)
将是正确的,因此您将移动其中一个元素,尽管已经进行了最佳分割。
请注意我在代码中的left < mid
而不仅仅是100 | 10 120 | 90 -> 100 10 | 120 | 90
。你需要类似的东西来检查你是否应该继续。
您需要考虑的一个例子是您需要进一步增加更大的一面:
import rollup from 'rollup'
这可能会使您的代码更加复杂。
答案 1 :(得分:1)
这可以使用Two Pointers
的概念来完成。所以首先将主数组视为3
子数组的连接。 A
,B
和C
。现在我们可以首先计算所有数组元素的总和,这表明所考虑的数组具有所有元素。
所以现在我们需要跟踪原始数组的3个连续子阵列的总和。在这里考虑我们在这里有3个数组
A ---> Starting from the left-side (index 0)
B ---> Middle sub-array
C ---> Starting from the right-side (index n-1)
这里的答案应该是min(sumOfA,min(sumOfB,sumOfC))
最大化。
这里我们已经存储了子数组B
中所有元素的总和,因为它具有数组的所有元素。 A
和C
为空。现在我们将从结尾处逐个删除元素,并将该值添加到适当的子数组A
或C
,我们需要通过减去它来从B
中删除它。
现在问题仍然是要删除哪个元素。为此,我们将检查A
和C
的值以及总和低于其他值的人,我们将从该端添加元素到特定子数组。
这里可能出现的另一个问题是终止条件。终止条件为Sum of B > Sum of A && Sum of B > Sum of C
。因此,当B
的总和变得小于其他两个子阵列中的任何一个时,我们需要停在那里。
这种方法的复杂性:O(n)
代码:
import java.util.*;
class Main
{
public static void main(String args[])
{
long arr[]={9, 12, 4, 7, 10, 2, 5, 8, 11, 3};
long sumOfA=0;
long sumOfB=0;
long sumOfC=0;
int a = 0; //set end of sub-array A
int b = arr.length-1; //set start of sub-array-C
long maximum =0; // Minimum of sum of all subarrays should be maximum,
// That will be sufficient to get the answer
long answer=0;
int answer_a=0;
int answer_b=0;
for(int i=0;i<arr.length;i++)
{
sumOfB+=arr[i];
}
for(int i=0;i<arr.length;i++)
{
long minimum = Math.min(sumOfA , Math.min(sumOfB,sumOfC));
if(minimum>=maximum)
{
answer_a=a;
answer_b=b;
ArrayList<Long> list=new ArrayList<Long>(); //To calculate the answer
list.add(sumOfA);
list.add(sumOfB);
list.add(sumOfC);
Collections.sort(list);
answer=Math.max(answer,list.get(0)+list.get(1)); //take minimum two elements
maximum=minimum;
}
if(sumOfB < sumOfC || sumOfB < sumOfA)
break;
if(a>=b) //If both pointer passes to each other
break;
if(sumOfA == sumOfC)
{
if(arr[a]<arr[b]) //take minimum element
{
sumOfA+=arr[a];
sumOfB-=arr[a];
a++; //move a to next element
}
else
{
sumOfC+=arr[b];
sumOfB-=arr[b];
b--; //move b to prev element
}
}
else if(sumOfA > sumOfC)
{
sumOfC+=arr[b];
sumOfB-=arr[b];
b--;
}
else
{
sumOfA+=arr[a];
sumOfB-=arr[a];
a++;
}
}
System.out.println("a(exclsive) : "+answer_a);
System.out.println("b(exclsive) : "+answer_b);
System.out.println("Answer : "+answer);
}
}
回答[9, 12, 4, 7, 10, 2, 5, 8, 11, 3]
:
a(exclsive) : 3
b(exclsive) : 6
Answer : 46
回答[6, 8, 3, 5, 7, 2, 4, 6]
:
a(exclsive) : 2
b(exclsive) : 4
Answer : 26