はあなたの例のような出力を生成するいくつかのPythonコードである:
def f(low, high):
ranges = collections.deque([(low, high)])
while ranges:
low, high = ranges.popleft()
mid = (low + high) // 2
yield mid
if low < mid:
ranges.append((low, mid))
if mid + 1 < high:
ranges.append((mid + 1, high))
例:Pythonで慣例であるように
>>> list(f(0, 20))
[10, 5, 15, 2, 8, 13, 18, 1, 4, 7, 9, 12, 14, 17, 19, 0, 3, 6, 11, 16]
low, high
範囲は、終点を除外するので、結果が含まれてい0から19までの数字。
このコードでは、依然として処理が必要な部分範囲を格納するためにFIFOが使用されます。 FIFOはフルレンジで初期化されます。各反復では、次の範囲がポップされ、中間点が生成されます。次に、空でない場合、現在の範囲の下位および上位の下位範囲がFIFOに追加されます。
編集:ここC99に完全に異なる実装である:
#include <stdio.h>
int main()
{
const unsigned n = 20;
for (unsigned i = 1; n >> (i - 1); ++i) {
unsigned last = n; // guaranteed to be different from all x values
unsigned count = 1;
for (unsigned j = 1; j < (1 << i); ++j) {
const unsigned x = (n * j) >> i;
if (last == x) {
++count;
} else {
if (count == 1 && !(j & 1)) {
printf("%u\n", last);
}
count = 1;
last = x;
}
}
if (count == 1)
printf("%u\n", last);
}
return 0;
}
これは、整数は、すでに以前の反復で発生したかどうかを決定するためにいくつかのトリックを使用してFIFOの必要性を回避します。
あなたはFIFOの最大サイズを知っているので(これは(n + 1)/ 2のようなものですが、これをもう一度確認する必要があります)、キューに入れられた範囲を保持するためにリングバッファを使用します。
編集2:これはC99のさらに別の解決策です。ループの反復の半分だけを実行し、ビットのオペレーションと加算のみを使用し、乗算や除算は使用しないように最適化されています。また、より簡潔で、結果に0
が含まれていないので、最初に意図したとおりにこれを最初にすることができます。
for (int i = 1; n >> (i - 1); ++i) {
const int m = 1 << i;
for (int x = n; x < (n << i); x += n << 1) {
const int k = x & (m - 1);
if (m - n <= k && k < n)
printf("%u\n", x >> i);
}
}
(これは私が最初から右に書くことを意図したコードですが、それはそれのまわりで私の頭をラップするために私にいくつかの時間がかかりました。)
サンプルケースに必要な完全な出力を提供してください。 –
でも、あなたが割り当てたページしか使えないのですか? –
これはよく似た質問への回答です。http://stackoverflow.com/a/11761192/1009831 –