Binary search for first occurrence of k

落爺英雄遲暮 提交于 2019-12-05 01:41:51

问题


I have code that searches a sorted array and returns the index of the first occurrence of k. I am wondering whether its possible to write this code using

while(left<right) 

instead of

while(left<=right)

Here is the full code:

public static int searchFirstOfK(List<Integer> A, int k) {
   int left = 0, right = A.size() - 1, result = -1;
   // A.subList(left, right + 1) is the candidate set.
   while (left <= right) {
      int mid = left + ((right - left) / 2);
      if (A.get(mid) > k) {
         right = mid - 1;
      } else if (A.get(mid) == k) {
         result = mid;
         // Nothing to the right of mid can be the first occurrence of k.
         right = mid - 1;
      } else { // A.get(mid) < k
         left = mid + 1;
      }
   }
   return result;
}

How do I know when to use left is less than or equal to right, or just use left is less than right.


回答1:


Building on this answer to another binary search question: How can I simplify this working Binary Search code in C?

If you want to find the position of the first occurrence, you can't stop when you find a matching element. Your search should look like this (of course this assumes that the list is sorted):

int findFirst(List<Integer> list, int valueToFind)
{
    int pos=0;
    int limit=list.size();
    while(pos<limit)
    {
        int testpos = pos+((limit-pos)>>1);

        if (list.get(testpos)<valueToFind)
            pos=testpos+1;
        else
            limit=testpos;
    }
    if (pos < list.size() && list.get(pos)==valueToFind)
        return pos;
    else
        return -1;
}

Note that we only need to do one comparison per iteration. The binary search finds the unique position where all the preceding elements are less than valueToFind and all the following elements are greater or equal, and then it checks to see if the value you're looking for is actually there.

The linked answer highlights several advantages of writing a binary search this way.




回答2:


Simply put No.

Consider the case of array having only one element i.e., {0} and the element to be searched is 0 as well.

In this case, left == right, but if your condition is while(left<right), then searchFirstOfK will return -1.


This answer is in context of the posted code. If we are talking about alternatives so that we can use while(left<right) then Matt Timmermans's answer is correct and is an even better approach.

Below is a comparison of Matt (OP - Let's call it Normal Binary) and Matt Timmermans (Let's call it Optimized Binary) approaches for a list containing values between 0 and 5000000:




回答3:


This is an extremely interesting question. The thing is there is a way by which you can make your binary search right always. The thing is determining the correct ranges and avoiding the single element stuck-out behavior.

while(left+1<right)
{
   m = (left+right)/2;
   if(check condition is true)
      left = m;
   else
      right =  m;
}

Only key thing to remember is you always make the left as the smallest condition unsatisfying element and right as the biggest condition satisfying element. That way you won't get stuck up. Once you understand the range division by this method, you will never fail at binary search.

The above initialization will give you the largest condition satisfying element.

By changing the initialization you can get variety of elements (like small condition satisfying element).



来源:https://stackoverflow.com/questions/46795712/binary-search-for-first-occurrence-of-k

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!