程序在数组中查找与给定值异或的对

Posted

技术标签:

【中文标题】程序在数组中查找与给定值异或的对【英文标题】:Program to find pairs in array that XOR to a given value 【发布时间】:2016-12-06 15:21:14 【问题描述】:

我得到一个数组和一个值 x。

输入示例:

2 3
1 2

其中 n(数组长度)= 2,值 x = 3,下一行 (1, 2) 包含数组中的值。我必须找到索引对 i, j 以便 a[i] XOR a[j] = x。

我实现了什么:

import java.util.HashSet;
import java.util.Scanner;

public class Main 

  public static void main(String[] args) 
   Scanner sc = new Scanner(System.in);

   int n = sc.nextInt();
   int x = sc.nextInt();

   int[] arr = new int[n];

   HashSet<Integer> hash = new HashSet<Integer>();

   for (int i = 0; i < n; i++) 
     arr[i] = sc.nextInt();
     hash.add(arr[i]);
   

   int count = 0;

   for (int i = 0; i < n; i++) 
     if (hash.contains(arr[i]^x)) 
       count++;
     
   

   System.out.println(count/2);
  


我将结果除以 2,因为我们只想计算给定对一次(只计算 [1, 2] 而不是 [1, 2] 和 [2, 1])。

我通过了上面输出为1 的给定测试,以及输出为2 的补充测试。

6 1
5 1 2 3 4 1

但是,我似乎没有看到一些额外的失败。

【问题讨论】:

当你说你必须找到成对的指标时,程序不应该显示这些指标,还是只是为了计算有多少? 【参考方案1】:

问题是您检查了“包含”,但对于重复值,这只会返回一次。通过使用集合,您可以丢弃重复项。相反,您应该有一个出现次数的 HashMap:

Map<Integer, Integer> hash = new HashMap<>();

for (int i = 0; i < n; i++) 
    arr[i] = sc.nextInt();
    if (!hash.containsKey(arr[i])) 
        hash.put(arr[i], 0)
    
    hash.put(arr[i], hash.get(arr[i]) + 1);


int count = 0;

for (int i = 0; i < n; i++) 
    if (hash.containsKey(arr[i]^x)) 
        count += hash.get(arr[i]^x);
    

【讨论】:

并保留 System.out.println(count/2) ? 是的,因为您说要计算组合而不是排列 只是一个想法,如果x = 0,这可能无法按预期工作。在这种情况下,它会找到n/2 额外的解决方案,因为它会将每个数字与其自身结合起来。如果ij 可能相同,那么这很好。【参考方案2】:

您将count 除以2 作为最终答案的逻辑不正确。 将您的逻辑替换为以下内容:

HashSet<Integer> hash = new HashSet<Integer>();

   for (int i = 0; i < n; i++) 
     arr[i] = sc.nextInt();
   

   int count = 0;

   for (int i = 0; i < n; i++) 
     if (hash.contains(arr[i]^x)) 
       count++;
     
     hash.add(arr[i]);
   

   System.out.println(count);

【讨论】:

嗨。我认为您注意到的内容是正确的,我刚刚更正了它,但似乎我仍然未能通过一些测试用例......还有其他想法吗? 看看@fafl 的回答。我想它可能对你有帮助【参考方案3】:

您的程序没有正确处理重复的数字。它处理5 1 2 3 4 1 好的,因为1 不是解决方案的一部分。如果是的话呢?

假设号码a[i] ^ a[j]a[i] ^ a[k] 一样是一个解决方案。换句话说,a[j] == a[k]hash.contains(arr[i]^x) 行只会计算一次 a[i]

您可以通过嵌套 for 循环来解决此问题。

for (int i = ...) 
  for (int j = ...) 
    if (a[i] ^ a[j] == x) 
      count++;
    
  

这种方法可以让您摆脱hash 集。如果您足够聪明地填写 ... 部分,则可以避免重复计算这些对,并且不必将 count 除以 2。

【讨论】:

我认为哈希的想法是在 O(n) 而不是 O(n^2) 中解决这个问题 确实,您的解决方案是正确的,但使用哈希的重点是将算法减少到 O(n)。

以上是关于程序在数组中查找与给定值异或的对的主要内容,如果未能解决你的问题,请参考以下文章

面试题:找出数组中只出现一次的2个数(异或的巧妙应用)(出现3次)

与数组中元素的最大异或值(字典树)(小于等于某元素的最大异或值)

js中value^= 是啥意思

[算法]位运算之二

剑指offer数组中只出现一次的数

最长异或路径值