为什么在这个二进制搜索中返回低,但不高?

时间:2015-12-16 06:03:48

标签: java arrays duplicates binary-search

  

给定一个未排序的数组nums,每个包含n + 1个整数   整数介于1和n之间(含),证明至少有一个   必须存在重复的数字。假设只有一个副本   数字,找到重复的。

     

注意:

     
      
  1. 您不能修改数组(假设数组是只读的)。

  2.   
  3. 您必须只使用常数,O(1)额外空格。

  4.   
  5. 数组中只有一个重复的数字,但可以重复多次。

  6.   

对于注释1,我们不能对数组进行排序,对于注释2,我们不能使用散列。我想我们可以在这里使用二进制搜索。

假设我们这个数组有重复的数字4:

[1, 4(was 2), 3, 4, 5, 6, 4(was 7), 8, 9, 4]

我们的想法是通过范围过滤器(如[7,9])查看数组,可能会出现2种情况:

案例1:范围包含重复元素,在这种情况下,我们可以在过滤器中找到的元素数量必须大于它应具有的元素数量。例如,如果我们看[3,4],我们会找到5个元素。如果没有重复,那么应该只有两个[3,4]。

这是正确的,因为其他一些元素可以重命名为该组,但不能重命名。在这种情况下,元素的预期数量是[3,4],但我们有一个额外的4(作为副本),然后两个4重命名,这就是为什么我们有5。

案例2:范围不包含重复元素,在这种情况下,我们在过滤器中可以找到的元素数量必须等于或小于元素数量。

以下是我的更新代码。我不确定哪一个在最后一行返回。虽然我测试过,发现低是正确的,但我仍然不知道原因。

public int findDuplicate(int[] nums) {
    int low = 1, high = nums.length - 1;
    while(low <= high){
        int mid = low + (high - low) / 2;
        int count = 0;
       //count the number of elements in the filter [low,mid]
        for(int i = 0; i < nums.length; i++){
            if(nums[i] <= mid && nums[i]>=low){
                count++;
            }
        }
        if(count > mid-low+1){  //the duplicate would be in the left half
            high = mid;
        } else {          //the duplicate would be in the right half
            low = mid + 1;
        }
    }
    return low; // Why we should return low here, not high?
}

1 个答案:

答案 0 :(得分:2)

目前尚不清楚为什么您认为必须返回low而不是high。我怀疑你没有用许多不同类型的输入来测试它。对于输入1,1,2,高和低都将为0.无论您返回high还是low,答案都将是错误的。

换句话说:

  • 实施没有正确解决问题,结果不正确
  • 问题“要说谎还是高”是一个错误的问题

您的算法的解释听起来是正确的。问题是,你没有实际实现你在那里解释的内容。您谈论计算范围内的元素,调整范围的下限和上限,但在实现中,您计算​​nums[I] <= mid,因此只有上限更改(mid),下限总是(隐式)0。这与您的解释不符。你没有正确实现你的想法。