Bir aralıkta iki sayının maksimum XOR değerini bulma: ikinci dereceden daha iyisini yapabilir miyiz?


14

İki ve sayısı verildiğini ve l \ le i, \, j \ le r için bulmak istediğimizi varsayalım .lrmax(ij)li,jr

Saf algoritma tüm olası çiftleri kontrol eder; örneğin yakutta:

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

Ben anlamda biz ikinci dereceden daha iyisini yapabiliriz söyledi. Bu sorun için daha iyi bir algoritma var mı?


Sen izin gerektiği jkadar devam i+1..rve iüzerinden çalışmasını l...r-1kesin konuşmak gerekirse.
Ahmet Alp Balkan

Yanıtlar:


20

ve ikili gösteriminin uzunluğunda doğrusal çalışma zamanını başarabiliriz :nlr

Her iki değer için aynı olan ve ikili gösterimindeki öneki , aralarındaki tüm değerler için de aynıdır. Yani bu bitler daima olacaktır .plr0

Yana , bu ön eki Aşağıdaki küçük olacak de ve içinde . Ayrıca, ve sayılarının ikisi de aralıktadır.r>l1r0lp10n|p|1p01n|p|1

Yani aradığımız maksimum değer .0|p|1n|p|


1
Kolaydı! Sanırım bu soruna daha çok düşünmeliydim.
Jacopo Notarstefano

Konuyu başlatan "sayılarda ikinci dereceden daha iyi" istedi. Bu sayıların boyutunda doğrusaldır, bu yüzden sayıların kendisinde logaritmiktir.
gnasher729

18

Bunu yapmak mümkündür zaman.O(logr)

aralığındaki herhangi iki tamsayıdan mümkün olan maksimum XOR, tamsayı olduğu varsayılarak belirlenebilir . Bu değer eşittir , burada , daha büyük olacak şekilde en küçük değerdir . [l,r]lrl,r2p1p2plr

İşte C ++ 'da bir uygulama

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

Bu algoritmanın arkasındaki mantığı açıklayabilir misiniz?
sk1pro99

Bu video size yardımcı olabilir: youtube.com/watch?v=3j-ok4gMjXU
Jack Kinsella

0

'Küçük' ve 'yüksek' arasındaki xor değerini en üst düzeye çıkarmamız gerekir. Öyleyse bunu anlamak için bir örnek alalım.

5 xor 2 = 101 xor 010 birinci durum: Aralıktaki her iki değer için de MSB biti ayarlanmamıştır. kalan alt bitleri en üst düzeye çıkarmak. Bildiğimiz gibi, her şey 11 olduğunda, daha düşük bitlerin hepsinin 3 olacağı anlamına gelecektir. Sorun 2 ila 5 arasındaki aralıktan bahsediyorsa, aralıkta 3 tane var. Tek yapmamız gereken, 2 değerden daha büyük olan en yüksek MSB setini bulmak ve alt bitler için kalan 1'leri eklemek.

ikinci durum: MSB'nin xor yapan aralıktaki her iki değer için ayarlandığı durumda olduğu gibi, bu bitler kesinlikle 0 olarak ayarlanmış olacaktır ve daha düşük bitlere geri dönmemiz gerekir. Yine daha düşük bitler için ilk durumla aynı mantığı tekrarlamamız gerekir. örnek: (10, 12) (1010, 1100) Her ikisinde de MSB'nin 1 olarak ayarlandığını görebileceğiniz gibi, 010 ve 100 olan daha düşük bitlere geri dönmeliyiz. Şimdi bu sorun ilk durumla aynı.

Bunu kodlamanın birkaç yolu vardır. Yaptığım sadece 'küçük' ve 'yüksek' arasındaki xor yapmak ve hem 'küçük' hem de 'yüksek' MSB biti varsa MSB bitini kaldıracaktır. Durum böyle değilse, MSB bitini koruyacaktır. Bundan sonra, xored çıktıda 2'nin maksimum gücünü bularak ve 1'den çıkararak tüm düşük bitleri 1 yapmaya çalışıyorum.

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

Cevabı bulmak için l ve r ' nin XOR'unu kullanabilirsiniz .

Diyelim ki, l = 4 ve r = 6.

l = 100, r = 110 (bu sayıların ikili eşdeğerleri)

l⊕r = 0 10

Bunun anlamı, aradığınız maksimum değer kesinlikle ilk bitine (MSB) sıfır olarak sahip olacaktır. (Düşünün, maksimum değerinizin ilk bitte 1 olması bile mümkün mü? 01010 ve 00101 olsaydı, xor = 01 111 olurdu, yani 01010 ve 00101 arasındaki maksimum değer kesinlikle bir 1 soldan ikinci bit, bir elde etmek mümkün değildir 1 soldan birinci bit sol yani ikinci bit öncesi)

Böylece, maksimum değeri bulmak için kalan 2 bit ile kalırsınız. Bizde n bit olduğunda mümkün olan maksimum değerin = 2 n −1 olduğunu biliyoruz, bu nedenle bu durumda cevap 2 2 -1 = 4-1 = 3 olacaktır.

Yukarıdaki örnekte, bunun için genel bir algoritma yapabiliriz.

Adım 1. num = maksimumu ( l , r ) temsil etmek için gereken bit sayısı

Adım 2. res = lr

Adım 3. pos = ayarlanır birinci bit pozisyonu sol res (0-esaslı indeks)

Adım 4. n = num - konum

Adım 5. ans = 2 n −1

Zaman karmaşıklığı = O (n)


-1

Her ikili basamak için 4 olasılık vardır: 1_ve_1, 1_ve_0, 0_ve_1 veya 0_ve_0. Olası daha düşük basamaklar, bir sonraki basamağın seçtiği xor çıkışında hiç kaybolmaz veya kaybolmaz şekilde küçük bir fark yaratmaz. Mümkün olan en iyi algoritma, tüm düşük basamakları yok saymak ve daha yüksek basamaklar hakkında daha önceki seçenekler göz önüne alındığında, yalnızca sonraki 2 mevcut olanı dikkate almaktır. Bu 1_and_1 veya 0_and_0 ise, seçim açıktır, ancak bu rakam 1_and_0 vs 0_and_1 (eşit xor ama eşit olmayan bir değere sahip) ise, yinelemeli olarak https://en.wikipedia.org/wiki/Edit_distance algoritmasına eşit olmalıdır , yani en büyük kütük karesi.


1
"Alt basamak", "log kaybolan küçük" veya "bu ... en büyük günlük karesi anlamına gelen" ile ne demek istediğinizden emin değilim. Açıklığa kavuşturabilir misiniz?
David Richerby

-1

32 bit aralıklarla O(1)Hacker Rank yazımlarında bu çözümle daha yeni karşılaştım . Nasıl çalıştığı hakkında hiçbir fikrim yok, ama işe yarıyor. (Belki birisi neden işe yaradığını açıklayabilir.)

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

Kaynak: https://www.hackerrank.com/challenges/maximizing-xor/editorial


2
Cevabınız (düzeltmeden sonra) ysb.4'lerden nasıl farklıdır (neler olduğunu açıklamanın yanı sıra)? 'B dönüşü' kararsız 'b' ile ne yapar? Maalesef sağladığınız bağlantıya erişemiyorum.
Evil
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.