Пожалуйста, прочтите новое правило об ограничении использования AI-инструментов. ×
Изменения рейтингов за последние раунды временно удалены. Скоро они будут возвращены. ×

Блог пользователя Gordon-Freeman

Автор Gordon-Freeman, история, 4 дня назад, По-английски

Can someone explain to me how do we choose ranges when doing BinarySearch i solved a lot of BS problems but to be honest i alwayes try differnt ways until one of them work... by mean whats the diffence between writing while(l<r) and while(l<=r) and while(l+1<r)...etc and when do we set r=mid and when r=mid-1 and same for l , please someone explain them all this is the only thing confuse me at BS problems

  • Проголосовать: нравится
  • +10
  • Проголосовать: не нравится

»
4 дня назад, # |
Rev. 3   Проголосовать: нравится +1 Проголосовать: не нравится

This is how I usually approach the binary search implementation.

First, I define an invariant for the pointers. For example, in some cases, I want to ensure that the left pointer (l) always points to a position that is strictly less than the answer, while the right pointer (r) should always be greater than or equal to the answer.

This approach is useful in cases where we want to find the lower_bound() of the answer, meaning the first element that is greater than or equal to x.

Based on that, I use the following implementation:

The initial value of l should satisfy < f(l) == false, meaning l points to a value less than the answer. The initial value of r should satisfy >= f(r) == true, meaning r points to a value greater than or equal to the answer. Next, I use the condition while (l + 1 < r). This ensures that when the loop exits, l and r are adjacent (l = r - 1), and we can determine that r will be the first element that is >= x.

To calculate the midpoint, I use:

int mid = (l + r) / 2;

if(f(mid)){
	r=mid; //this is because we know that mid is >= ans. But we dont know about mid - 1
}else{
	l=mid; // we know mid < ans
}

When the algorithm finishes you will have in r the first element >= x.

The main idea is to set that invariant (l < answer, r >= answer) and then the implementation gets easier.

This is how I approach BS problems. Correct me if there are any errors

  • »
    »
    4 дня назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    I think using the below formula is better in handling large constraints.

    mid=l+(r-l)/2;
    
»
4 дня назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

I always do:

while (l<=r) {
    mid=(l+r)/2;
    if (check(mid)) {
        res=mid;
        r=mid-1;
    }
    else l=mid+1;
}

Change the r=mid-1 and l=mid+1 depending on whether you need the maximum whatever or minimum whatever.

  • »
    »
    6 часов назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Can you give a small example to make sure iam getting it righ , thanks

    • »
      »
      »
      5 часов назад, # ^ |
      Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

      For example, if we have [1,3,5,7,9] and we are searching for the next number greater than 6

      set l=0, and r=4 (highest index),mid,res (predefined outside of while loop)

      First iteration of while loop: mid=(l+r)/2=(4+0)/2=2 check if vec(mid) (5)>6 it isn't, continue otherwise change l from 0 to mid+1 which is 2+1=3

      Second iteration of while loop: set mid=(l+r)/2=(3+4)/2=7/2=rounded down: 3 check if vec(mid) (7) >6, it is as 7>6: change r to mid-1 (r is now 2 and l is 3) update res to be mid (the index of the value)

      No third iteration of while loop, as it violates l<=r (3<=2 not true)

      Hope this helps! Feel free to ask me any questions.

»
4 дня назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

easy:

left search:
l, r = 0, n - 1
l <= r
l = m + 1
r = m - 1
return m

.

efficient:

left search:
l, r = 0, n - 1
l < r
l = m + 1
r = m
return l

right search:
l, r = 0, n
l < r
r = m
l = m + 1
return l - 1