【问题标题】:Finding the only repeating element in sorted array查找排序数组中唯一的重复元素
【发布时间】:2017-06-07 15:01:12
【问题描述】:

我知道在排序数组中查找非重复元素的 XOR 技巧(之前已经问过):

public int singleNumber(int[] nums) {
    int result = 0; 
    for (int i = 0; i < nums.length; i++) {
        result = result ^ nums[i]; 
    }
    return result; 
}

但是我们如何使用相同的逻辑来做相反的事情呢?

更具体地说:考虑一个排序数组,其中每个元素仅出现一次,我们如何找到在 O(1) 空间中重复的元素?

【问题讨论】:

  • Consider a sorted array where **each element but one occurs only once**, how do we find the one element that repeats 这句话不是矛盾吗?
  • 不是完全重复,但另一篇文章中提到的“简单线性搜索”会起作用。
  • 第n个,第(n+1)个元素的区别是一样的吗??
  • 我发布了自己的解决方案。我想太多了,因为我正在寻找基于 XOR 的解决方案,但我无法弄清楚。

标签: java arrays xor


【解决方案1】:

只有当你想丢弃 even 次重复时,XOR 技巧才是巧妙的。一种看待它的方法是说数组中所有元素的异或是该数组中奇怪重复元素的异或;因此,如果只有一个奇怪重复的元素,你可以通过这种方式找到它。而且您根本不需要对数组进行排序:

// could also have called it xorOfOddlyRepeatingIntsInArray(int[] a)
public static int findSingleNonEvenlyRepetingIntInUnsortedArray(int[] a) {
  int x = 0;
  for (int i: a) x ^= i;
  return x;
}

根据您的要求,这两个片段都在 O(1) 空间和 O(n) 时间的排序数组中找到重复元素:

public static int findSingleRepeatingIntInSortedArray1(int[] a) {
  for (int i=0; i<a.length-1; i++) if (a[i] == a[i+1]) return a[i];
  return -1;
}

public static int findSingleRepeatingIntInSortedArray2(int[] a) {
  for (int i=0; i<a.length-1; i++) if ((a[i] ^ a[i+1]) == 0) return a[i];
  return -1;
}

但您应该更喜欢版本 1,因为a[i] == a[i+1](a[i] ^ a[i+1]) == 0(a[i] - a[i+1]) == 0(a[i] &amp; a[i+1]) == a[i] 或其他神秘的变体更易读,以检查是否相等。 在这种情况下,Xor 不会给你买任何东西

对于笑声和咯咯笑声,此代码在 unsorted 数组中找到 O(1) space 中的单个重复值:

 public static int findSingleRepeatingIntInSortedArray3(int[] a) {
    for (int i=0; i<a.length; i++) {
       for (int j=i+1; j<a.length; j++) {
          if (a[i] == a[j]) return a[i];
       }
    }
    return 0;
 }

是的,它是 O(n^2) 时间,并且有更快的方法来找到第一个重复的元素(我想到了排序) - 但这是对问题的有效答案。

【讨论】:

    【解决方案2】:

    我认为有人删除了使用 XOR 的评论。这里是:

        private int returnNumber(int[] nums) {
        int result = 0;
        for (int i = 1; i < nums.length; i++) {
            if ((nums[i] ^ nums[i - 1]) == 0) {
                result = nums[i];
                break;
            }
        }
        return result;
    }
    

    我真的不确定这是否使用 O(1)。

    【讨论】:

    • 如果你的函数所需的空间(内存)没有随着输入的大小而增长(在这种情况下,nums 中的元素数量),那么你的算法在 O(1 )。因为不管nums.length,你总是使用相同的额外空间(对于iresult,并且,取决于平台/编译器/java内部,存储中间计算) - 你的代码是O(1)
    【解决方案3】:

    我没有设法找到基于 XOR 的解决方案,但这个令人惊讶的简单解决方案就地解决了问题。

    public static int getRepeatingValue(int[] nums) {
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == nums[i - 1]) {
                return nums[i]; 
            }
        }
        return -1; 
    }
    

    【讨论】:

    • O(1) Space 怎么样??
    • @SrikanthA 我的意思是它就地完成它,而不使用额外的数据结构。
    • 所以,它不是 O(1) 空间。 Q/A 必须相应更正
    • Srikanth:O(1) 空间意味着空间是恒定的,而不是“1”。这个答案是 O(1)
    猜你喜欢
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    相关资源
    最近更新 更多