0

各要素に添字を含む、特定の長さの配列を作成する最も効率的な方法は何ですか?

私のダミーレベルのコードで考えられる説明:

/**
 * The IndGen function returns an integer array with the specified dimensions.
 *  
 *  Each element of the returned integer array is set to the value of its 
 *  one-dimensional subscript.
 *  
 *  @see Modeled on IDL's INDGEN function: 
 *      http://idlastro.gsfc.nasa.gov/idl_html_help/INDGEN.html 
 *  
 *  @params size
 *  @return int[size], each element set to value of its subscript
 *  @author you
 *  
 *  */

public int[] IndGen(int size) {
    int[] result = new int[size];
    for (int i = 0; i < size; i++) result[i] = i;
    return result;
}

doc スタイルなど、その他のヒントも歓迎します。

編集

forたとえば、Copying an Arrayのように、ループが他の方法と比較してどれほど非効率的であるかを他の場所で読みました。

クローンを使用: 93 ミリ秒

System.arraycopy を使用: 110 ミリ秒

Arrays.copyOf の使用: 187 ミリ秒

for ループの使用: 422 ミリ秒

このサイトのいくつかの質問に対する想像力に富んだ回答に感銘を受けまし。いくつかの方法を提案する可能性のある答えは次のとおりです。

public class To100 {
public static void main(String[] args) {
        String set = new java.util.BitSet() {{ set(1, 100+1); }}.toString();
        System.out.append(set, 1, set.length()-1);
    }
}

この困難な問題に取り組む準備ができていない場合は、発散する必要はありません。次の未回答の質問に進んでください。解決できる質問です。

4

3 に答える 3

3

数テラバイトのメモリを一度に使用すること、特にそれらを同時に計算することは不可能であるため、ジェネレータの使用を検討することもできます。(おそらく、配列をループするつもりでしたよね?) ジェネレーターを使用すると、配列を初期化する必要がなく (すぐに使い始めることができます)、ほとんどメモリを使用しません (O(1))。

以下に実装例を含めました。longプリミティブの制限によって制限されます。

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Counter implements Iterator<Long> {
    private long count;
    private final long max;

    public Counter(long start, long endInclusive) {
        this.count = start;
        this.max = endInclusive;
    }

    @Override
    public boolean hasNext() {
        return count <= max;
    }

    @Override
    public Long next() {
        if (this.hasNext())
            return count++;
        else
            throw new NoSuchElementException();

    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

以下の使用例をご覧ください。

Iterator<Long> i = new Counter(0, 50);
while (i.hasNext()) {
    System.out.println(i.next());  // Prints 0 to 50
}
于 2012-06-09T00:57:05.390 に答える
2

私が考えることができるのは、 "i++" の代わりに "++i" を使用することだけですが、Javaコンパイラにはすでにこの最適化があると思います。

それ以外は、これはほとんど最高のアルゴリズムです。

配列を持っているかのように動作するクラスを作成できますが、それは取得したのと同じ数を返すだけです (別名恒等関数) が、それはあなたが求めているものではありません。

于 2012-06-08T23:39:48.380 に答える
0

他の人が回答で言ったように、少なくとも小さなサイズの配列の場合、あなたのコードは私が考えることができる最も効率的なものにすでに近づいています。これらの配列を何度も作成する必要があり、それらが非常に大きい場合は、for ループで継続的に反復する代わりに、すべての配列を一度作成してからコピーすることができます。配列が非常に大きい場合、コピー操作は配列を反復処理するよりも高速になります。次のようになります (この例では、最大 1000 要素)。

public static int[][] cache = {{0},{0,1},{0,1,2},{0,1,2,3},{0,1,2,3,4}, ..., {0,1,2,...,998,999}};

次に、これらの配列を何度も作成する必要があるコードから、次のようなものを使用します。

int[] arrayOf50Elements = Arrays.copyOf(cache[49], 50);

この方法では、速度を向上させるために大量のメモリを使用していることに注意してください。これらの配列を何度も作成する必要があり、配列が非常に大きく、最大速度が要件の1つである場合にのみ、これが複雑になる価値があることを強調したいと思います. 私が考えることができるほとんどの状況では、あなたが提案した解決策が最善の解決策になるでしょう。

編集:必要な膨大な量のデータとメモリを見てきました。私が提案するアプローチでは、n^2 のオーダーのメモリが必要になります。ここで、n は予想される最大の整数です。この場合、膨大な量のメモリが必要になるため、これは実用的ではありません。これを忘れてください。他の人に役立つかもしれないので、投稿を残します。

于 2012-06-09T00:15:31.697 に答える