การหาค่า XOR สูงสุดของตัวเลขสองตัวในช่วงเวลาหนึ่ง: เราจะทำได้ดีกว่าสมการกำลังสองหรือไม่?


14

สมมติว่าเรากำลังได้รับสองหมายเลขและและที่เราต้องการที่จะหาสำหรับL \ le i, \, J \ le Rlrmax(ij)li,jr

อัลกอริทึมnaïveเพียงตรวจสอบคู่ที่เป็นไปได้ทั้งหมด เช่นในทับทิมเรามี:

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..rและiวิ่งl...r-1ให้แม่นยำ
Ahmet Alp Balkan

คำตอบ:


20

เราสามารถบรรลุรันไทม์เชิงเส้นในความยาวของการเป็นตัวแทนไบนารีของและ :nlr

คำนำหน้าในการแทนค่าไบนารี่ของและซึ่งเป็นค่าเดียวกันสำหรับทั้งสองค่าจะเหมือนกันสำหรับค่าทั้งหมดระหว่างค่าเหล่านั้น ดังนั้นบิตเหล่านี้จะเป็นเสมอplr0

ตั้งแต่บิตต่อไปคำนำหน้านี้จะเป็นในและในลิตรนอกจากนี้ตัวเลขและทั้งคู่อยู่ในช่วงเวลาr>l1r0lp10n|p|1p01n|p|1

ดังนั้นสูงสุดที่เรากำลังมองหาคือ|}0|p|1n|p|


1
นั่นเป็นเรื่องง่าย! ฉันคิดว่าฉันควรจะได้รับปัญหานี้คิดเพิ่มเติม
Jacopo Notarstefano

ผู้เริ่มต้นเธรดขอให้ "ดีกว่ากำลังสองในตัวเลข" นี่คือเส้นตรงในขนาดของตัวเลขดังนั้นมันจึงเป็นลอการิทึมในตัวเลขเอง
gnasher729

18

มันเป็นไปได้ที่จะทำในเวลาO(logr)

XOR ที่เป็นไปได้สูงสุดของจำนวนเต็มสองจำนวนใด ๆ จากช่วงเวลาสามารถกำหนดได้จาก , สมมติว่าเป็นจำนวนเต็ม ค่านี้จะมีค่าเท่ากับที่คือค่าที่น้อยที่สุดเช่นที่มีขนาดใหญ่กว่าR [l,r]lrl,r2p1p2plr

นี่คือการใช้งานใน 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?v=3j-ok4gMjXU
Jack Kinsella

0

เราจำเป็นต้องเพิ่มค่าแฮคเกอร์ระหว่าง 'เล็ก' และ 'สูง' ลองยกตัวอย่างเพื่อทำความเข้าใจสิ่งนี้

5 xor 2 = 101 xor 010 กรณีแรก: MSB บิตไม่ได้ถูกตั้งค่าสำหรับค่าทั้งสองในช่วงถ้าต้องการเพิ่มค่าสูงสุดแล้วสิ่งที่เราต้องทำคือรักษา MSB ที่ 5 (100) ตามที่คิดไว้ การเพิ่มบิตที่เหลือให้มากที่สุด อย่างที่เรารู้ว่าบิตที่ต่ำกว่าทั้งหมดจะเป็นหนึ่งสำหรับกรณีเมื่อทุกอย่างคือ 11 ซึ่งไม่มีอะไรเลยนอกจาก 3 คือ 2 ^ 2-1 เนื่องจากปัญหากำลังพูดถึงช่วงระหว่าง 2 ถึง 5 เราจึงมี 3 อยู่ในช่วง defintely ดังนั้นสิ่งที่เราต้องทำคือการหาชุด MSB ที่สูงที่สุดในค่าที่มากกว่า 2 และเพิ่ม 1 ที่เหลือสำหรับบิตที่ต่ำกว่า

กรณีที่สอง: สำหรับกรณีที่ MSB ถูกตั้งค่าสำหรับทั้งสองค่าในช่วงที่ทำการ xor จะกำหนดบิตเหล่านั้นเป็น 0 และเราต้องกลับไปที่บิตที่ต่ำกว่า อีกครั้งสำหรับบิตที่ต่ำกว่าเราจำเป็นต้องทำซ้ำตรรกะเดียวกันเป็นกรณีแรก ตัวอย่าง: (10, 12) (1010, 1100) อย่างที่คุณเห็นทั้งคู่ตั้ง MSB เป็น 1 จากนั้นเราต้องกลับไปที่บิตต่ำกว่าซึ่งคือ 010 และ 100 ตอนนี้ปัญหานี้เหมือนกับกรณีแรก

มีหลายวิธีในการรหัสนี้ สิ่งที่ฉันทำคือการทำเพียงแค่ xor ระหว่าง 'เล็ก' และ 'สูง' และนั่นจะลบบิต MSB ถ้าทั้ง 'เล็ก' และ 'สูง' มีชุดบิต MSB ในกรณีที่ไม่ใช่ในกรณีนี้จะเก็บบิต MSB ไว้ หลังจากนั้นฉันพยายามทำให้บิตที่ต่ำกว่าทั้งหมด 1 โดยหาพลังงานสูงสุดที่ 2 ในเอาต์พุต xored และลบออกจาก 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

คุณสามารถใช้ XOR ของlและrเพื่อค้นหาคำตอบ

สมมติว่า l = 4 และ r = 6

l = 100, r = 110 (เทียบเท่าไบนารีของตัวเลขเหล่านี้)

l⊕r = 0 10

หมายความว่าอะไรค่าสูงสุดที่คุณต้องการจะมีบิตแรก (MSB) เป็นศูนย์ (ลองคิดดูสิมันเป็นไปได้ไหมที่ค่าสูงสุดของคุณจะมี1ในบิตแรกแทนถ้าเป็น 01010 และ 00101, xor จะเป็น = 01 111 คือค่าสูงสุดระหว่าง 01010 และ 00101 จะมีแน่นอน1ในบิตที่สองจากซ้ายมันเป็นไปไม่ได้ที่จะได้รับ1ก่อนบิตที่สองจากซ้ายคือในบิตแรกจากซ้าย)

ดังนั้นคุณเหลือ 2 บิตที่เหลือเพื่อค้นหาค่าสูงสุด เรารู้ว่าค่าที่เป็นไปได้สูงสุดเมื่อเรามีnบิตกับเราคือ = 2 n −1 ดังนั้นคำตอบในกรณีนี้จะเป็น 2 2 -1 = 4-1 = 3

จากตัวอย่างข้างต้นเราสามารถสร้างอัลกอริทึมทั่วไปสำหรับสิ่งนี้

ขั้นตอนที่ 1 num = จำนวนบิตที่ต้องใช้เพื่อแทนค่า max ( l , r )

ขั้นตอนที่ 2 res = lr

ขั้นตอนที่ 3 pos = ตำแหน่งของบิตแรกที่ตั้งจากทางซ้ายเป็นres (การจัดทำดัชนีแบบ 0)

ขั้นตอนที่ 4 n = num - pos

ขั้นตอนที่ 5. ans = 2 n −1

ความซับซ้อนของเวลา = O (n)


-1

สำหรับเลขฐานสองแต่ละตัวมีความเป็นไปได้ 4 ประการคือ 1_and_1, 1_and_0, 0_and_1 หรือ 0_and_0 ตัวเลขที่ต่ำกว่าที่เป็นไปได้จะทำให้ไม่มีความแตกต่างเล็ก ๆ น้อย ๆ หรือไม่มีความแตกต่างอย่างมากกับเอาต์พุต xor ของตัวเลือกของตัวเลขถัดไป อัลกอริทึมที่ดีที่สุดที่เป็นไปได้คือละเว้นตัวเลขที่ต่ำกว่าทั้งหมดและพิจารณาเฉพาะ 2 ตัวถัดไปที่มีให้เลือกก่อนหน้านี้เกี่ยวกับตัวเลขที่สูงขึ้น หากนี่คือ 1_and_1 หรือ 0_and_0 ตัวเลือกนั้นชัดเจน แต่หากตัวเลขนี้คือ 1_and_0 เทียบกับ 0_and_1 (ซึ่งมีค่า xor เท่ากัน แต่มีค่าไม่เท่ากัน) ควรเรียกใช้ซ้ำhttps://en.wikipedia.org/wiki/Edit_distanceอัลกอริธึม หมายถึงกรณีที่เลวร้ายที่สุดของบันทึกกำลังสอง


1
ฉันไม่แน่ใจว่าสิ่งที่คุณหมายถึงโดย "ตัวเลขที่ต่ำกว่า", "log-vanishingly-small" หรือ "มัน ... หมายถึงกรณีที่แย่ที่สุดของ log squared" คุณช่วยอธิบายได้ไหม
David Richerby

-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' ทำอะไรกับ indeclared 'b' และขออภัย แต่ฉันไม่สามารถเข้าถึงลิงก์ที่คุณให้ไว้
Evil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.