在一个间隔中找到两个数字的最大异或:我们能做得比二次更好吗?


14

lrmax(ij)li,jr

天真的算法只检查所有可能的对。例如在红宝石中,我们有:

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要精确。
Ahmet Alp Balkan

Answers:


20

我们可以在和的二进制表示形式的长度中实现线性运行时:nr

和的二进制表示形式中的前缀对两个值都相同,对它们之间的所有值也相同。因此,这些位将始终为。plr0

由于,以下此前缀的比特将是的和在。此外,数字和都处于间隔中。r>l1r0lp10n|p|1p01n|p|1

因此,我们要寻找的最大值是。0|p|1n|p|


1
好吧,那很容易!我想我应该多考虑这个问题。
Jacopo Notarstefano 2014年

线程启动器要求“在数字上胜于二次数”。这些数字的大小是线性的,因此数字本身是对数的。
gnasher729

18

可以在时间内完成。O(logr)

从时间间隔的任何两个整数的最大可能的XOR 可以从被确定- [R 假设- [R是整数。此值等于2 p - 1,其中p是最小的值,使得2 p大于ř[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?
Jack Kinsella

0

我们需要最大化“小”与“高”之间的异或。因此,让我们举一个例子来理解这一点。

5 xor 2 = 101 xor 010第一种情况:范围内的两个值均未设置MSB位如果要最大程度地提高此值,则我们需要保持MSB为5(100)并考虑最大化剩余的低位。众所周知,当所有内容均为11时,低位全部为1,仅3,即2 ^ 2-1。由于问题在于2到5之间的范围,因此我们肯定在该范围内有3。因此,我们要做的就是找出2个值中较大的最高MSB集,并将其余的1与低位相加。

第二种情况:至于在xor范围内将两个值都设置为MSB的情况,则肯定会将那些位设置为0,我们需要返回低位。同样,对于低位,我们需要重复与第一种情况相同的逻辑。示例:(10,12)(1010,1100)如您所见,两个MSB都设置为1,那么我们必须返回到较低的位010和100。现在,此问题与第一种情况相同。

有几种方法可以对此进行编码。我所做的只是在“小”和“高”之间进行异或运算,如果“小”和“高”都设置了MSB位,则将删除MSB位。如果不是这种情况,它将保留MSB位。之后,我试图通过在异或输出中找出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,则不可能在从左数第二个位之前获得1,即从左数第一位为1)

因此,剩下的2位可以找到最大值。我们知道,当我们有n位时,最大可能值为= 2 n -1,因此在这种情况下的答案将是2 2 -1 = 4-1 = 3。

从上面的示例中,我们可以为此制定一个通用算法。

步骤1. num =表示max(lr)所需的位数

步骤2. RES = ř

步骤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。可能的低位数字与下一位数字的异或输出没有差别或对数消失很小。最好的算法是忽略所有低位数字,并考虑较早的有关高位数字的选择,仅考虑下2个可用数字。如果这是1_and_1或0_and_0,则选择是明确的,但如果此数字是1_and_0与0_and_1(具有相等的xor但不相等的值),则递归地应等于https://en.wikipedia.org/wiki/Edit_distance算法,表示对数平方的最坏情况。


1
我不确定您所说的“低位数字”,“对数消失”或“它……表示对数平方的最坏情况”是什么意思。你能澄清一下吗?
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的答案有何不同(除了他解释了所发生的事情)?“返回b”与未声明的“ b”有什么关系?很抱歉,但我无法访问您提供的链接。
Evil
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.