2017-05-11 18 views
2

を使用して連続したサブリストの負の合計を見つける:私は、元のリストのすべての要素私は、次のコードを最適化しようとしていたJava 8

ため startIndexから newIndex + 1に反復避けたい

private final static class SubarrayProcessorNegativeSumStrategy 
    implements SubarrayProcessorStrategy { 
    @Override public Integer apply(Integer[] array) { 
     final List<Integer> numbers = Arrays.asList(array); 
     return (int) IntStream.range(0, numbers.size()) 
      .map(index -> findNegativeSums(numbers, index)).sum(); 
    } 
    private Integer findNegativeSums(final List<Integer> numbers, 
            final Integer startIndex) { 
    final Integer numbersSize = numbers.size(); 
    if (startIndex < numbersSize) { 
     return (int) IntStream.range(startIndex, numbers.size()) 
     .map(newIndex -> numbers.subList(startIndex, newIndex + 1) 
     .stream().mapToInt(x -> x).sum()) 
     .filter(sum -> sum < 0).count(); 
    } else { 
     return 0; 
    } 
} 

numbers.subList(startIndex, newIndex + 1).stream().mapToInt(x -> x).sum()

私はこれをどのように達成することができますか?同じ結果を得るために改善を施すことができるのであれば?

あなたはStream APIを経由して、それを実装する場合は、List APIの迂回を経由する必要がないあなたに

よろしく、

+1

あなたのコードがどのように機能するかを理解するための少しのテストコードを提供できますか? 最適化の主な目的は何ですか:ランタイムまたはメモリフットプリント? – cyberbrain

+0

こんにちは@cyberbrain、例えばA = [1、-2、4、-5、1]は9を出力します。私はメモリを最適化しようとしています。ありがとう –

+1

@ eduardo.leonこの小さな例を含めて質問を更新してください – Flown

答えて

6

ありがとうございます。さらに、«要素数の合計»あなたは、単一のflatMapストリーム操作を実行する場合は、すべての要素の合計数です:

private final static class SubarrayProcessorNegativeSumStrategy 
    implements SubarrayProcessorStrategy { 
    @Override public Integer apply(Integer[] array) { 
     return (int)IntStream.rangeClosed(0, array.length) 
      .flatMap(index -> IntStream.range(0, index) 
       .map(newIndex -> Arrays.stream(array,newIndex,index).mapToInt(x->x).sum()) 
       .filter(sum -> sum < 0)) 
      .count(); 
    } 
} 

これはまだネストされた反復の同じ時間の複雑さを持っています。実行時間を最適化したい場合は、ステートフルな操作がタスクにはるかに適していますが、これはStream APIの良いユースケースではありません。通常のループを使用すると、単純明快です:

private final static class SubarrayProcessorNegativeSumStrategy 
    implements SubarrayProcessorStrategy { 
    @Override public Integer apply(Integer[] array) { 
     int count=0; 
     for(int index = 0; index < array.length; index++) { 
      for(int newIndex = index, currSum = 0; newIndex < array.length; newIndex++) { 
       currSum += array[newIndex]; 
       if(currSum < 0) count++; 
      } 
     } 
     return count; 
    } 
} 
+0

実際にはブロックのネストは非常に良く、IMHO –

+0

@Federico Peralta Schaffner:彼らは 'O(n³)'時間の複雑さを 'O(n²)'に変えます... – Holger

+0

これは私の答えを恥にします約。一を足す。 – Eugene

2

私が最初にあなたが気にすべてのインデックスを見つけることで、わずかに異なるアプローチを取りました。

3, 2, 1 
3, 2 
3 
2, 1 
2 
1 

をそしてちょうどsumにこれらのインデックスから値を収集する:配列[5,6,7]の例では、インデックスを生成します。

private static long applyMine(int[] array) { 
    return IntStream.range(0, array.length) 
      .flatMap(i -> IntStream.iterate(i, x -> x + 1) 
        .takeWhile(x -> x != array.length) 
        .map(m -> IntStream.iterate(array.length - i, x -> x - 1) 
          .takeWhile(x -> x >= array.length - m) 
          .map(x -> array[x - 1]) 
          .sum()) 
        .filter(s -> s < 0)) 
      .count(); 
} 
+0

'takeWhile'はJava 9です...' iterate(seed、next) 'と' takeWhile(predicate) 'の組み合わせは' iterate(seed、predicate、next) 'と書くことができます。現在のコンテキストでは 'IntStream.range'よりも優先されます。 – Holger

+0

@Holger私はjdk-9が私が持っているデフォルトであることを忘れています:(あなたのコメントに完全に同意します)私はこれを置く時間が非常に長くなりました。 – Eugene

関連する問題