public class Kadane {
double maxSubarray(double[] a) {
double max_so_far = 0;
double max_ending_here = 0;
for(int i = 0; i < a.length; i++) {
max_ending_here = Math.max(0, max_ending_here + a[i]);
max_so_far = Math.max(max_so_far, max_ending_here);
}
return max_so_far;
}
}
上面的代码返回最大子数组的总和。
我如何返回具有最大总和的子数组?
答案 0 :(得分:12)
这样的事情:
public class Kadane {
double[] maxSubarray(double[] a) {
double max_so_far = 0;
double max_ending_here = 0;
int max_start_index = 0;
int startIndex = 0;
int max_end_index = -1;
for(int i = 0; i < a.length; i++) {
if(0 > max_ending_here +a[i]) {
startIndex = i+1;
max_ending_here = 0;
}
else {
max_ending_here += a[i];
}
if(max_ending_here > max_so_far) {
max_so_far = max_ending_here;
max_start_index = startIndex;
max_end_index = i;
}
}
if(max_start_index <= max_end_index) {
return Arrays.copyOfRange(a, max_start_index, max_end_index+1);
}
return null;
}
}
答案 1 :(得分:2)
上面的代码有错误。应该是:
max_ending_here = Math.max(a[i], max_ending_here + a[i]);
NOT:
max_ending_here = Math.max(0, max_ending_here + a[i]);
如果没有,则会失败,例如:2,4,22,19,-48,-5,20,40并返回55而不是60的正确答案。
查看Kadane算法答案 2 :(得分:0)
我在列表中维护max_so_far:
for(int i = 0;i<N;i++){
max_end_here = Math.max(seq[i], max_end_here + seq[i]);
sum_list.add(max_end_here);
// System.out.println(max_end_here);
max_so_far = Math.max(max_so_far, max_end_here);
}
然后搜索列表中的最大总和,其索引为子序列结束。 从索引作为结束开始并向后搜索,找到其值为正的最后一个索引。子序列开始是这个索引。
for(int i=sum_list.size()-1; i>=0; i--){
if(sum_list.get(i) == max_so_far){
end = i;
while(sum_list.get(i) > 0 && i>=0){
i--;
}
start = (i==-1)?0:i+1;
break;
}
}
答案 3 :(得分:0)
与算法密切相关的更简单方法。
int main()
{
int a[]={-2, 1, -3, 4, -1, 2, 1, -5, 4};
int size=sizeof(a)/sizeof(a[0]);
int startIndex=0,endIndex=0,i,j;
int max_so_far=0,max_sum=-999;
for(i=0;i<size;i++)
{
max_so_far=max_so_far+a[i];//kadane's algorithm step 1
if(max_so_far>max_sum) //computing max
{
max_sum=max_so_far;
endIndex=i;
}
if(max_so_far<0)
{
max_so_far=0;
startIndex=i+1;
}
}
cout<<max_so_far<<" "<<startIndex<<" "<<endIndex;
getchar();
return 0;
}
一旦你有开始和结束索引。
for(i=startIndex;i<=endIndex;i++)
{
cout<<a[i];
}
答案 4 :(得分:0)
我们可以使用以下代码跟踪最大子阵列:
import java.util.Arrays;
public class KadaneSolution4MaxSubArray{
public static void main(String[]args){
int [] array = new int[]{13,-3,-25,20 ,-3 ,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
int[] maxSubArray = maxSubArrayUsingKadaneSol(array);
for(int e : maxSubArray){
System.out.print(e+"\t");
}
System.out.println();
}
public static int[] maxSubArrayUsingKadaneSol(int array[]){
long maxSoFar =array[0];
long maxEndingHere =array[0];
int startIndex = 0;
int endIndex =0;
int j=1;
for(; j< array.length ;j++){
int val = array[j];
if(val >= val+maxEndingHere){
maxEndingHere = val;
startIndex = j;
}else {
maxEndingHere += val;
};
if(maxSoFar < maxEndingHere){
maxSoFar = maxEndingHere;
endIndex = j;
}
}
return Arrays.copyOfRange(array,startIndex,endIndex+1);
}
}
<强> P.S。假设给定数组是Max子阵列问题的候选者,并且没有所有元素为负
答案 5 :(得分:0)
每次启动新的子阵列总和时,更新可能的左(起始)索引。更新max_sum后,更新最后的左右(结束)。还保持一个触发器,告诉是否创建了一个新的子数组和。
int last = 0;
int sum = Integer.MIN_VALUE;
boolean fOrReset = true;
int _L = -1, L = -1, R = -1;
for (int j = 0; j < arr.length; j++) {
last += arr[j];
if (fOrReset) {
_L = j+1;
}
fOrReset = false;
if (sum < last) {
sum = last;
L = _L;
R = j+1;
}
if (last < 0) {
last = 0;
fOrReset = true;
}
}
答案 6 :(得分:0)
private static int[] applyKadaneAlgorithmGetSubarrayOptimized(int[] input) {
int localMax = input[0];
int globalMax = input[0];
int start = 0;
int end = 0;
for (int i = 1; i < input.length; i++) {
localMax = Math.max(localMax + input[i], input[i]);
if(localMax == input[i]) { //this is similar as --> input[i] > (localMax + input[i])
start = i;
}
if(localMax > globalMax) {
end = i;
}
globalMax = Math.max(localMax, globalMax);
}
//Below condition only occur`enter code here`s when all members of the array are negative integers
//Example: {-9, -10, -6, -7, -8, -1, -2, -4}
if(start > end) {
start = end;
}
return Arrays.copyOfRange(input, start, end + 1);
}
答案 7 :(得分:0)
我知道这是一个旧线程,但是为了清晰起见,我想分享我的解决方案版本。
trait SomeType
trait SomeTrait[T <: SomeType] {
def get(i: Int): Option[SomeType]
}
trait ConcreteType extends SomeType
object ConcreteType extends SomeTrait[ConcreteType]
def temp[T <: SomeType]()(implicit tag: ClassTag[T]): Option[T] = {
asInstanceOf[SomeTrait[T]].get(1)
}
答案 8 :(得分:0)
另一种 C++ 实现,包括 Kadane(实际上只是动态编程方法)和使用索引计算和一些注释扩展的 Kadane:
int maxSubArray(vector<int>& nums)
{
int n = nums.size();
if(n == 0) return INT_MIN;
// max sum that ends at index I
int sumMaxI = nums[0];
// total max sum
int sumMax = nums[0];
for(int i = 1; i < n; i++)
{
int curr = nums[i];
// calc current max sum that ends at I
int currSumMaxI = sumMaxI + curr;
// calc new max sum that ends at I
sumMaxI = max(currSumMaxI, curr);
// calc new total max sum
sumMax = max(sumMax, sumMaxI);
}
return sumMax;
}
int maxSubArray_findBeginEnd(vector<int>& nums)
{
int n = nums.size();
if(n == 0) return INT_MIN;
// max sum that ends at index I
int sumMaxI = nums[0];
// start index for max sum (end index is I)
int sumMaxIStart = 0;
// total max sum
int sumMax = nums[0];
// start and end index for total max sum
int sumMaxStart = 0;
int sumMaxEnd = 0;
for(int i = 1; i < nums.size(); i++)
{
int curr = nums[i];
// calc current max sum that ends at I
int currSumMaxI = sumMaxI + curr;
// calc new min sum that ends at I and its starting index
// this part is equal to: sumMaxI = max(currSumMaxI, curr);
// but additionaly enables to save new start index as well
if(curr > currSumMaxI)
{
sumMaxI = curr;
sumMaxIStart = i;
}
else
sumMaxI = currSumMaxI;
// calculate total max sum
// this part is equal to: sumMax = max(sumMax, sumMaxI);
if(sumMaxI > sumMax)
{
sumMax = sumMaxI;
sumMaxStart = sumMaxIStart;
sumMaxEnd = i;
}
// this part is to additionaly capture longest subarray among all that have max sum
// also, of all subarrays with max sum and max len, one with smallest index
// will be captured
else if(sumMaxI == sumMax)
{
if(i - sumMaxIStart > sumMaxEnd - sumMaxStart)
{
sumMaxStart = sumMaxIStart;
sumMaxEnd = i;
}
}
}
// check validity of start and end indices
int checkSum = 0;
for(int i = sumMaxStart; i <= sumMaxEnd; i++)
checkSum += nums[i];
assert(checkSum == sumMax);
// output indices
cout << "Max subarray indices: [" << sumMaxStart << "," << sumMaxEnd << "]" << endl;
return sumMax;
}