BinarySearch在列表中找不到元素,即使它在那里:Java

时间:2011-05-05 20:08:27

标签: java algorithm binary-search

有谁可以指出我在哪里出错?我使用调试器逐步完成它,看起来我的算法应该是找到搜索键,但事实并非如此。 (为了检查,我打印出'找到索引',然后打印[sorted]列表的内容;我搜索的元素123,在列表中,但返回'未找到'值为-1。)

public int binarySearch(ArrayList<Integer> list, int key){
    int foundAtIndex  = -1;
    int midPoint = list.size()/2;
    int midPointValue = list.get(midPoint);

    if(list.size() > 1){
        if(midPointValue == key){
            foundAtIndex = midPoint;
        }
        else if(midPointValue > key){
            ArrayList<Integer> newList = new ArrayList<Integer>();
            for(int i = 0; i < midPoint; i++){
                newList.add(list.get(i));
            }
            midPoint = midPoint / 2;
            binarySearch(newList, key);
        }
        else if(midPointValue < key){
            ArrayList<Integer> newList = new ArrayList<Integer>();
            for(int j = midPoint+1; j < list.size(); j++){
                newList.add(list.get(j));
            }
            midPoint = midPoint / 2;
            binarySearch(newList, key);
        }
    }
    else if(list.size() == 1){
        if(list.get(0) == key){
            foundAtIndex = 0;
        }
    }

    //return the index where the key was found, or -1 if not found
    return foundAtIndex;
}
编辑:好的,现在它找到它,但我的问题是我需要返回原始数组中找到的索引。实际上,它将其缩小然后返回'newList'中元素的索引。所以它总是将它返回到'newList'的索引中。换句话说,我希望返回一个实际的foundAtIndex(该值位于原始数组中的位置),而不是布尔值,“是/未找到”值。

3 个答案:

答案 0 :(得分:3)

每次拨打binarySearch(newList, key);时,您都会丢失返回结果。

您需要设置foundIndex = binarySearch(newList,key)

另外,因为您依靠list.size()作为中点 - 您需要调整返回结果(否则它将始终为-1或0)。

答案 1 :(得分:2)

您不存储递归调用的返回值。替换两行

binarySearch(newList, key);

通过

foundAtIndex = binarySearch(newList, key);

它应该有用。

答案 2 :(得分:1)

这是一个在原始列表中返回索引的解决方案。主要更改:当您对binarySearch进行递归调用时,将newList的偏移量添加到其结果中(与list相比)。在midPointValue > key中,此偏移量为零,因此无需添加任何内容。如果midPointValue < key则偏移量为midPoint

public int binarySearch(ArrayList<Integer> list, int key){
  int foundAtIndex  = -1;
  int midPoint = list.size()/2;
  int midPointValue = list.get(midPoint);

  if(list.size() > 1){
    if(midPointValue == key){
      foundAtIndex = midPoint;
    }
    else if(midPointValue > key){
      ArrayList<Integer> newList = new ArrayList<Integer>();
      for(int i = 0; i < midPoint; i++){
        newList.add(list.get(i));
      }
      return binarySearch(newList, key);
    }
    else if(midPointValue < key){
      ArrayList<Integer> newList = new ArrayList<Integer>();
      for(int j = midPoint+1; j < list.size(); j++){
        newList.add(list.get(j));
      }
      return midPoint + binarySearch(newList, key);
    }
  }
  else if(list.size() == 1){
    if(list.get(0) == key){
      foundAtIndex = 0;
    }
  }
  //return the index where the key was found, or -1 if not found
  return foundAtIndex;
}

补充要点:

  • 在进行下一次递归调用之前,无需设置midPoint。
  • 在方法中有多个返回是完全合法的。无需将结果一直传播下来。
  • pointmidPoint中的midPointValue有点多余。 Varialbe名称太长会使代码更难理解。
  • 最后,无需创建新列表并将原始列表中的元素复制到此新列表中。您只需通过添加辅助方法,告诉该方法仅检查原始列表的某个部分。

以下是我写这个方法的方法:

public int binarySearch(ArrayList<Integer> list, int key) {
  return binarySearch(list, key, 0, list.size());
}

public int binarySearch(ArrayList<Integer> list, int key, int begin, int end) {

  if(end <= begin) 
    return -1; // Range is empty => key wasn't found

  int mid = (begin + end) / 2;
  int midValue = list.get(mid);

  if(midValue == key) 
    return mid;
  else if(midValue < key) 
    return binarySearch(list, begin, mid);
  else
    return binarySearch(list, mid + 1, end);
}