구간에서 두 숫자의 최대 XOR 찾기 : 이차보다 더 잘 할 수 있습니까?


14

두 개의 숫자 r 이 주어지고 l i에 대해 max ( i j ) 를 찾고 싶다고 가정 해 봅시다 .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

답변:


20

lr 의 이진 표현 길이 에서 선형 런타임을 달성 할 수 있습니다 .nlr

프리픽스 의 이진 표현에서 Lpl두 값에 대해 동일하며 두 값 사이의 모든 값에 대해서도 동일합니다. 이 비트는 항상r 입니다.0

이후 이 프리픽스는 다음의 비트가 될 것이다 1 에서 R0 에서 L . 또한, 숫자 p 10 n | p | 1p 01 n | p | 1 은 모두 구간에 있습니다.r>l1r0lp10n|p|1p01n|p|1

따라서 우리가 찾고있는 최대 값은 .0|p|1n|p|


1
글쎄, 그것은 쉬웠다! 나는이 문제에 더 많은 생각을 주었어야한다고 생각한다.
Jacopo Notarstefano

스레드 스타터는 "숫자에서 이차보다 낫다"고 물었다. 이것은 숫자의 크기가 선형이므로 숫자 자체에서 로그입니다.
gnasher729

18

시간 내에 수행 할 수 있습니다.O(logr)

[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

'작은'과 '높은'사이의 xor를 최대화해야합니다. 이것을 이해하기 위해 예를 들어 봅시다.

5 xor 2 = 101 xor 010 첫 번째 경우 : MSB 비트가 범위의 두 값 모두에 대해 설정되지 않았습니다.이를 최대화하려면 MSB를 5 (100) 그대로 유지하고 생각해야합니다. 나머지 하위 비트를 최대화합니다. 우리가 알다시피, 모든 것이 11 일 때 더 낮은 비트는 모두 하나가 될 것입니다. 문제가 2에서 5 사이의 범위에 대해 이야기하고 있기 때문에 범위에 3이 있습니다. 따라서 우리가해야 할 일은 2 개의 값 중 더 큰 MSB 세트를 찾아서 더 낮은 비트에 대해 나머지 1을 추가하는 것입니다.

두 번째 경우 : MSB가 xor를 수행하는 범위의 값 모두에 대해 설정된 경우에는 해당 비트가 0으로 설정되며 하위 비트로 돌아 가야합니다. 더 낮은 비트에 대해서도 첫 번째 경우와 동일한 논리를 반복해야합니다. 예 : (10, 12) (1010, 1100) 둘 다 MSB가 1로 설정되어 있음을 알 수 있듯이 하위 비트 (010과 100)로 돌아 가야합니다. 이제이 문제는 첫 번째 경우와 동일합니다.

이것을 코딩하는 몇 가지 방법이 있습니다. 내가 한 것은 '작은'과 '높은'사이의 xor 만하는 것이며 '작은'과 '높은'모두에 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)를 확실히 0으로합니다. 최대 값이해야하는 (그것도 가능하며, 그것에 대해 생각 하나를 대신 첫 번째 비트에가의 XOR을했을 = 01010 및 00101 있었다면? 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 = 개수 - 위치

단계 5. ans = 2 n -1

시간 복잡도 = O (n)


-1

각 이진수에는 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
"낮은 자릿수", "로그-소멸 적으로 작은"또는 "최악의 로그 제곱을 의미하는 것"이 ​​무엇을 의미하는지 잘 모르겠습니다. 당신은 명확히 할 수 있습니까?
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'는 선언 된 'b'와 어떤 관계가 있습니까? 죄송합니다. 제공하신 링크에 액세스 할 수 없습니다.
Evil
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.