間隔内の2つの数値の最大XORを見つける:二次式よりも良いことはできますか?


14

lr L I 最大jljr

ナイーブアルゴリズムは、考えられるすべてのペアを単純にチェックします。たとえば、ルビーでは次のようになります。

def max_xor(l, r)
  max = 0

  (l..r).each do |i|
    (i..r).each do |j|
      if (i ^ j > max)
        max = i ^ j
      end
    end
  end

  max
end

私たちはより良い次より行うことができます。この問題のためのより良いアルゴリズムはありますか?


あなたはさせてくださいj通るi+1..riを介して実行l...r-1正確に。
アフメットアルプバルカン

回答:


20

およびバイナリ表現の長さで線形ランタイムを実現できます。l rnlr

とバイナリ表現のプレフィックスは、両方の値で同じですが、それらの間のすべての値でも同じです。したがって、これらのビットは常になり。l r 0plr0

以来、、このプレフィックス以下のビットになりますにおける及びで。さらに、数値とは両方とも間隔内にあります。1 r 0 l p 10 n | p | 1 p 01 n | p | 1r>l1r0lp10n|p|1p01n|p|1

探している最大値はです。0|p|1n|p|


1
まあ、それは簡単でした!この問題をもっと考えるべきだったと思います。
ヤコポNotarstefano

スレッドスターターは「数字の二次式よりも良い」を求めました。これは、数値のサイズが線形であるため、数値自体は対数です。
gnasher729

18

それを行うことが可能である時間。Oログr

区間の任意の2つの整数の最大XORは、から決定できますは整数であると仮定します。この値はに等しく、はがよりも大きい最小値です。 [lr]lrlr2p1p2plr

C ++での実装は次のとおりです。

int maximumXOR(int l, int r) {
    int q = l ^ r, a = 1;
    while(q){
        q /= 2;
        a <<= 1;
    }
    return --a;
}

このアルゴリズムの背後にある理論的根拠を説明できますか?
sk1pro99

この動画が役立つかもしれません:youtube.com/watch
ジャックキンセラ

0

「小さい」と「高い」の間のxorを最大化する必要があります。それでは、例を理解してみましょう。

5 xor 2 = 101 xor 010最初の場合:範囲内の両方の値にMSBビットが設定されていません。これを最大化する場合は、MSBを5(100)のままにして、残りの下位ビットを最大化します。私たちが知っているように、下位ビットはすべて、すべてが3以外の11、つまり2 ^ 2-1の場合に1になります。問題は2〜5の範囲に関するものであるため、最終的には3の範囲になります。したがって、必要なのは、2つの値のうち大きい方で最も高いMSBセットを見つけ、残りの1を下位ビットに追加することです。

2番目のケース:MSBがxorを実行する範囲内の両方の値に設定されている場合、これらのビットは確実に0に設定されるため、下位ビットに戻る必要があります。下位ビットについても、最初のケースと同じロジックを繰り返す必要があります。例:(10、12)(1010、1100)両方ともMSBが1に設定されていることがわかるように、下位のビット010と100に戻らなければなりません。この問題は最初のケースと同じです。

これをコーディングする方法はいくつかあります。私がしたことは、 'small'と 'high'のxorだけを行うことで、 'small'と 'high'の両方にMSBビットが設定されている場合、MSBビットが削除されます。そうでない場合は、MSBビットが保持されます。その後、xored出力で2の最大電力を見つけ、1から減算することにより、下位ビットをすべて1にしようとしています。

def range_xor_max(small, high):
  if small == high:
    return 0
  xor = small ^ high
  #how many power of 2 is present
  how_many_power_of_2 = math.log(xor, 2)
  #we need to make all one's below the highest set bit
  return 2**int(math.floor(how_many_power_of_2)+1) - 1

0

さて、あなたは答えを見つけるためにlrの XORを使用できます。

l = 4およびr = 6と仮定します。

l = 100、r = 110(これらの数値のバイナリ等価)

l⊕r= 0 10

つまり、探している最大値の最初のビット(MSB)は必ずゼロになります。(それについて考えてみてください、あなたの最大値が最初のビットに1を持っている可能性さえありますか?それが01010と00101だった場合、xorは= 01 111でした。すなわち01010と00101の間の最大値は間違いなく持っています。1左から、その2番目のビットで、取得することはできません1)左から1ビット目に左すなわちから2ビット目の前に

したがって、最大値を見つけるために残りの2ビットが残っています。nビットがある場合の最大値は= 2 n -1であるため、この場合の答えは2 2 -1 = 4-1 = 3になります。

上記の例から、このための一般的なアルゴリズムを作成できます。

ステップ1. num = max(lr)を表すために必要なビット数

ステップ2. RES = LR

ステップ3. pos = resの左から設定される最初のビットの位置(0ベースのインデックス付け)

ステップ4. n = num - pos

ステップ5. ans = 2 n -1

時間の複雑さ= O(n)


-1

各2進数には、1_and_1、1_and_0、0_and_1、または0_and_0の4つの可能性があります。可能性のある下位桁は、次の桁の選択のxor出力に差異を生じないか、対数がわずかに小さくなります。可能な限り最良のアルゴリズムは、下位の桁をすべて無視し、上位の桁に関する以前の選択を考慮して、次の2桁のみを考慮することです。これが1_and_1または0_and_0の場合、選択は明確ですが、この数字が1_and_0対0_and_1(xorは等しいが値は等しくない)の場合、再帰的にhttps://en.wikipedia.org/wiki/Edit_distanceアルゴリズムと等しくなります。対数の二乗の最悪の場合を意味します。


1
「下の桁」、「ログがゼロに近い」、または「...ログの2乗の最悪の場合を意味する」とはどういう意味かわかりません。明確にできますか?
デビッドリチャービー

-1

32ビット間隔の場合、O(1)Hacker Rank社説でこのソリューションに出会いました。どのように機能するのかわかりませんが、機能します。(おそらく誰かがそれが機能する理由を説明できるでしょう。)

def max_xor(L,R):
  v = L^R
  v |= v >> 1
  v |= v >> 2
  v |= v >> 4
  v |= v >> 8
  v |= v >> 16
  return b

ソース:https : //www.hackerrank.com/challenges/maximizing-xor/editorial


2
(修正後の)あなたの答えはysb.4とどう違うのか(彼は何が起こっているのかを説明した以外に)?'return b'は宣言されていない 'b'で何をしますか?申し訳ありませんが、提供されたリンクにアクセスできません。
邪悪な
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.