Tìm XOR tối đa của hai số trong một khoảng: chúng ta có thể làm tốt hơn bậc hai không?


14

Giả sử chúng ta đã cho hai số và và chúng ta muốn tìm cho .r max ( i j )lrmax(ij)li,jr

Thuật toán ngây thơ chỉ đơn giản là kiểm tra tất cả các cặp có thể; ví dụ trong ruby ​​chúng ta sẽ có:

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

Tôi cảm thấy rằng chúng ta có thể làm tốt hơn so với bậc hai. Có một thuật toán tốt hơn cho vấn đề này?


Bạn nên để jchạy qua i+1..richạy qua l...r-1cho chính xác.
Ahmet Alp Balkan

Câu trả lời:


20

Chúng ta có thể đạt được thời gian chạy tuyến tính theo độ dài của biểu diễn nhị phân của và :nlr

Tiền tố trong biểu diễn nhị phân của và , giống nhau cho cả hai giá trị, cũng giống nhau cho tất cả các giá trị giữa chúng. Vì vậy, các bit này sẽ luôn là .plr0

Vì , bit theo sau tiền tố này sẽ là in và in . Hơn nữa, các số và đều nằm trong khoảng.r>l1r0lp10n|p|1p01n|p|1

Vì vậy, mức tối đa chúng tôi đang tìm kiếm là .0|p|1n|p|


1
Vâng, đó là dễ dàng! Tôi đoán tôi nên suy nghĩ vấn đề này nhiều hơn.
Jacopo Notarstefano

Chủ đề bắt đầu yêu cầu "tốt hơn bậc hai trong các số". Đây là tuyến tính trong kích thước của các số, vì vậy nó là logarit trong chính các số đó.
gnasher729

18

Có thể làm điều đó trong thời gian .O(logr)

XOR tối đa có thể có của hai số nguyên bất kỳ trong một khoảng có thể được xác định từ l r , giả sử l , r là số nguyên. Giá trị này bằng 2 p - 1 , trong đó p là giá trị nhỏ nhất sao cho 2 p lớn hơn l r . [l,r]lrl,r2p1p2plr

Đây là một triển khai trong C ++

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

Bạn có thể giải thích lý do đằng sau thuật toán này?
sk1pro99

Video này có thể giúp bạn hiểu: youtube.com/watch?v=3j-ok4gMjXU
Jack Kinsella

0

Chúng ta cần tối đa hóa xor giữa 'nhỏ' và 'cao'. Vì vậy, hãy lấy một ví dụ để hiểu điều này.

5 xor 2 = 101 xor 010 trường hợp đầu tiên: Bit MSB không được đặt cho cả hai giá trị trong phạm vi. Nếu muốn tối đa hóa điều này thì điều chúng ta cần làm là giữ MSB ở mức 5 (100) như hiện tại và suy nghĩ về tối đa hóa các bit thấp hơn còn lại. Như chúng ta biết rằng tất cả các bit thấp hơn sẽ là một trong trường hợp khi mọi thứ là 11, không có gì ngoài 3 tức là 2 ^ 2-1. Vì vấn đề là nói về phạm vi từ 2 đến 5, chúng tôi chắc chắn có 3 trong phạm vi. Vì vậy, tất cả những gì chúng ta cần làm là tìm ra bộ MSB cao nhất trong 2 giá trị lớn hơn và thêm 1 còn lại cho các bit thấp hơn.

Trường hợp thứ hai: Đối với trường hợp khi MSB được đặt cho cả hai giá trị trong phạm vi, xor chắc chắn sẽ có các bit đó được đặt thành 0 và chúng ta cần quay lại các bit thấp hơn. Một lần nữa đối với các bit thấp hơn, chúng ta cần lặp lại logic tương tự như trường hợp đầu tiên. ví dụ: (10, 12) (1010, 1100) Như bạn có thể thấy cả hai đều có MSB được đặt là 1 thì chúng ta phải quay lại các bit thấp hơn là 010 và 100. Bây giờ vấn đề này giống như trường hợp đầu tiên.

Có một số cách để mã này. Những gì tôi đã làm là chỉ thực hiện xor giữa 'nhỏ' và 'cao' và điều đó sẽ loại bỏ bit MSB nếu cả 'nhỏ' và 'cao' đều có bit MSB được đặt. Trong trường hợp đó không phải là trường hợp thì nó sẽ bảo toàn bit MSB. Sau đó, tôi đang cố gắng tạo ra tất cả các bit thấp hơn 1 bằng cách tìm ra công suất tối đa là 2 trong đầu ra xored và trừ đi 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

Chà, bạn có thể sử dụng XOR của lr để tìm câu trả lời.

Giả sử, l = 4 và r = 6.

l = 100, r = 110 (tương đương nhị phân của các số này)

l⊕r = 0 10

Điều này có nghĩa là, giá trị tối đa bạn đang tìm kiếm chắc chắn sẽ có bit đầu tiên (MSB) là 0. (Hãy nghĩ về nó, thay vào đó, giá trị tối đa của bạn có thể có 1 trong bit đầu tiên không? Nếu đó là 01010 và 00101, xor sẽ có = 01 111 tức là giá trị tối đa trong khoảng từ 01010 đến 00101 chắc chắn sẽ có a 1 trong bit thứ hai của họ từ trái, không thể lấy 1 trước bit thứ hai từ trái tức là trong bit đầu tiên từ bên trái)

Vì vậy, bạn còn lại 2 bit còn lại để tìm mức tối đa. Chúng ta biết rằng giá trị tối đa có thể có khi chúng ta có n bit với chúng ta là = 2 n 1, do đó, câu trả lời trong trường hợp này sẽ là 2 2 -1 = 4-1 = 3.

Từ ví dụ trên, chúng ta có thể tạo ra một thuật toán chung cho việc này.

Bước 1. num = số bit cần thiết để biểu diễn max ( l , r )

Bước 2. res = lr

Bước 3. pos = Vị trí của bit đầu tiên được đặt từ bên trái trong độ phân giải (lập chỉ mục dựa trên 0)

Bước 4. n = num - pos

Bước 5. ans = 2 n 1

Độ phức tạp thời gian = O (n)


-1

Đối với mỗi chữ số nhị phân, có 4 khả năng: 1_and_1, 1_and_0, 0_and_1 hoặc 0_and_0. Các chữ số thấp hơn có thể làm cho không có hoặc chênh lệch log-vanishingly nhỏ với đầu ra xor của chữ số tiếp theo. Thuật toán tốt nhất có thể là bỏ qua tất cả các chữ số thấp hơn và chỉ xem xét 2 khả năng tiếp theo, đưa ra các lựa chọn trước đó về các chữ số cao hơn. Nếu đây là 1_and_1 hoặc 0_and_0, sự lựa chọn là rõ ràng, nhưng nếu chữ số này là 1_and_0 so với 0_and_1 (có xor bằng nhau nhưng giá trị không bằng nhau) thì nó sẽ bằng thuật toán https://en.wikipedia.org/wiki/Edit_distance , có nghĩa là trường hợp xấu nhất của bình phương đăng nhập.


1
Tôi không chắc ý của bạn là "chữ số thấp hơn", "log-vanishingly-small" hay "nó ... có nghĩa là trường hợp xấu nhất của bình phương log". Bạn có thể làm rõ?
David Richerby

-1

Đối với các khoảng thời gian 32 bit, tôi chỉ bắt gặp O(1)giải pháp này trên các bài xã luận của Hacker Rank. Tôi không biết làm thế nào nó hoạt động, nhưng nó hoạt động. (Có lẽ ai đó có thể giải thích tại sao nó hoạt động.)

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

Nguồn: https://www.hackerrank.com/challenges/maximizing-xor/editorial


2
Câu trả lời của bạn (sau khi sửa) khác với ysb.4 'như thế nào (ngoài việc anh ấy giải thích chuyện gì đang xảy ra)? 'Return b' làm gì với 'b' bị tịch thu? Và xin lỗi, nhưng tôi không thể truy cập vào liên kết bạn đã cung cấp.
Ác
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.