私はこの質問に取り組んでおり、解決策を考え出しています(1つまたは2つの条件を追加する必要があるかもしれません)が、これが正しい方法であるかどうかはわかりません.2つのループを使用するのは面倒で、これが効率的な方法です。誰かがそれを行うための素晴らしいトリックを持っているか、より良いアプローチがあればそれは素晴らしいことです:)。(言語は障壁ではありません)
私のアルゴリズム:
- まず、数値の最初の「0」の lsb ビットを見つけます
- 次に、この「0」ビットの隣にある次のセットビットを見つけます
- 「0」ビットを1に、「1」ビットを「0」に変更します
- あなたが得る数は次に小さいです
- すべてのビットが設定されている場合、同じ数の「1」ビットで次に小さい数はありません。
void nextSmaller(int number) {
int firstZeroBitHelper = 1, nextOneBitHelper;
while (firstZeroBitHelper < number) {
// when we find first lsb zero bit we'll stop
bool bit = number & firstZeroBitHelper;
if (bit == false)
break;
firstZeroBitHelper = firstZeroBitHelper << 1;
}
if (firstZeroBitHelper >= number) {
cout << "No minimum number exists" << endl;
return;
}
nextOneBitHelper = firstZeroBitHelper;
nextOneBitHelper = nextOneBitHelper << 1;
while (nextOneBitHelper < number) {
// when we get '1' after the previous zero we stop
bool bit = number & nextOneBitHelper;
if (bit == true)
break;
nextOneBitHelper = nextOneBitHelper << 1;
}
// change the first zero to 1
number = number | firstZeroBitHelper;
// change the next set bit to zero
number = number & ~nextOneBitHelper;
cout << number << endl;
}