рдореИрдВ рдмрд╛рдЗрдирд░реА рд╕рд░реНрдЪ рдирд╣реАрдВ рд▓рд┐рдЦ рд╕рдХрддрд╛

рд╣рд╛рд▓ рд╣реА рдореЗрдВ (рд╕рдЪрдореБрдЪ рджреЛ рд╕рд╛рд▓ рдкрд╣рд▓реЗ), рдПрдХ рд▓реЗрдЦ рдпрд╣рд╛рдВ рд╕реЗ рдЪрд▓рд╛ред рдХреЗрд╡рд▓ 10% рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╣реА рджреНрд╡рд┐рдЖрдзрд╛рд░реА рдЦреЛрдЬ рд▓рд┐рдЦрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВ ред рдмрд╛рдЗрдирд░реА рдЦреЛрдЬ рдПрдХ рдХреНрд▓рд╛рд╕рд┐рдХ рдЦреЛрдЬ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рд░рд▓ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╣реИ рдЬрд┐рд╕реЗ рдмрд╣реБрдд рдЖрд╕рд╛рдиреА рд╕реЗ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рд╣рдо рдПрдХ рдХреНрд░рдордмрджреНрдз рд╕рд░рдгреА рд▓реЗрддреЗ рд╣реИрдВ, рдмреАрдЪ рдореЗрдВ рджреЗрдЦрддреЗ рд╣реИрдВ, рдЕрдЧрд░ рд╣рдореЗрдВ рд╡рд╣рд╛рдВ рдХреЛрдИ рд╕рдВрдЦреНрдпрд╛ рдирд╣реАрдВ рдорд┐рд▓рддреА рд╣реИ, рддреЛ рдпрд╣ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдмреАрдЪ рдореЗрдВ рдХреНрдпрд╛ рд╣реИ - рд╣рдо рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЛ рдпрд╛ рддреЛ рдмрд╛рдИрдВ рдУрд░ рдПрдХ рд╣реА рд╡рд┐рдзрд┐ рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рдпрд╛ рджрд╛рдИрдВ рдУрд░, рдордзреНрдп рддрддреНрд╡ рдХреЛ рдкреБрдирдГ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ред рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рднреА, рдмрд╕ рдПрдХ рд╕рд░рдгреА рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╛рд░реЛрд╣ рд╣реИред рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд▓рдЧрднрдЧ рд╣рд░ рдЬрдЧрд╣ рд╡рд░реНрдгрд┐рдд рд╣реИ, рд╕рднреА рдХреАрдбрд╝реЗ рдкрдХрдбрд╝реЗ рдЧрдП рдФрд░ рд╡рд░реНрдгрд┐рдд рд╣реИрдВред

рдЗрд╕рд▓рд┐рдП, рдореИрдВ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рдЦреЛрдЬ рдХреЛ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ред рдореЗрд░реЗ рд▓рд┐рдП, рд╡рд╣ рдереЛрдбрд╝рд╛ рддреБрдЪреНрдЫ рдирд╣реАрдВ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдПрдХ рдирдХрд▓реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд╣реВрдВред рд▓реЗрдХрд┐рди рдпрд╣ рд╣реИ, рдореИрдВ рд╕рд┐рд░реНрдл рдПрдХ рдЫрд╛рддреНрд░ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдХреЛрдИ рдмрд╣рд╛рдирд╛ рдирд╣реАрдВ рд╣реИ? рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ, рдореИрдВ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рд╣реА рд╕реБрдВрджрд░ рдмрд╛рдЗрдирд░реА рдЦреЛрдЬ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ред рд╣рд░ рд╕рдордп рдореБрдЭреЗ рд╕рдорд╕реНрдпрд╛ рдпрд╛ рддреЛ рд╢реБрджреНрдзрддрд╛ рдХреЗ рд╕рд╛рде, рдпрд╛ рдкреВрд░реНрд╡рд╛рдЧреНрд░рд╣ рдХреЗ рд╕рд╛рде, рдпрд╛ рджреЛрдиреЛрдВ рдХреЗ рд╕рд╛рде рдорд┐рд▓рддреА рд╣реИред рддреЛ, рд╣рд╛рдБ, рд╢реАрд░реНрд╖рдХ рдереЛрдбрд╝рд╛ рдкреАрд▓рд╛ рд╣реИред
рдЗрд╕ рд╡рд┐рд╖рдп рдХреЛ рдкрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рджреНрд╡рд┐рдЖрдзрд╛рд░реА рдЦреЛрдЬ рдХреЗ рдЕрдкрдиреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд▓рд┐рдЦреЗрдВ - рдПрдХ рдХреНрд░рдордмрджреНрдз рд╕рд░рдгреА рдХреЗ рд▓рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдЦреЛрдЬ рдХреЛ рдкрд╣рд▓реЗ рддрддреНрд╡, рдпрд╛ рдХрд┐рд╕реА рднреА рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рддреБрд▓рдирд╛ рдХреЗ рд▓рд┐рдП, рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рдЦреЛрдЬ рд▓рд┐рдЦреЗрдВ

рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ C # рдореЗрдВ рдХреЛрдб рд▓рд┐рдЦреВрдВрдЧрд╛ред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдХреЗ рдкреНрд░рд╢рдВрд╕рдХ рдореЗрд░реЗ рдХреЛрдб рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕рдордЭ рдкрд╛рдПрдВрдЧреЗред рдореИрдВ рдЦреЛрдЬ рдХреА рд╕реАрдорд╛рдУрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдЖрдзреЗ-рдЕрдВрддрд░рд╛рд▓ [рдмрд╛рдПрдВ] рдХреЗ рд░реВрдк рдореЗрдВ рдХрд░реВрдВрдЧрд╛; рджрд╛рдпреЗрдВ), рдЕрд░реНрдерд╛рддреНред рдмрд╛рдПрдВ рдмрд┐рдВрджреБ рдЪрд╛рд▓реВ рд╣реИ, рдФрд░ рджрд╛рдпрд╛рдВ рдмрд┐рдВрджреБ рдмрдВрдж рд╣реИред рдЖрдзреЗ-рдЕрдВрддрд░рд╛рд▓ рдореЗрд░реЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИрдВ, рдореИрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрдирдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд┐рднрд┐рдиреНрди рдПрд▓реНрдЧреЛрд░рд┐рджрдо (рдЬреЛ рд╣рдо рдмрд╛рдж рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ) рдХреЗ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдЖрдзреЗ-рдЕрдВрддрд░рд╛рд▓ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдХреБрдЫ рдлрд╛рдпрджреЗ рд╣реИрдВред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, "рдПрдХреАрдХреГрдд рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╢реИрд▓реА" рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЖрдзреЗ-рдЕрдВрддрд░рд╛рд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЕрдзрд┐рдХ рд╕рд╣реА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд▓реВрдк рд▓рд┐рдЦрддрд╛ рд╣реВрдВ:
for (int i = 0; i < array.Length; i++)
:
for (int i = 0; i <= array.Length - 1; i++)

, , . :
static int BinarySearch_Rec_Wrapper(int[] array, int element)
{
    BinarySearch_Rec(array, element, 0, array.Length);
}



, . , . , ,
int mid = (left + right) / 2 
, (. ):
 int mid = left + (right - left) / 2

, . off-by-one. , :

, [0, 3) [4, 7), .. [left, mid) [mid + 1, right). , ┬л┬╗ ( ), , , , . , , , , .

, : [left, right], [left, mid тАФ 1] [mid + 1; right] ( , , ).
1 ( , ), тАФ 2 тАФ , .

, ( [left, mid) [mid, right)), 1 ( [left, mid] [mid + 1, right], [left, mid тАФ 1] [mid, right]).

, , , , (array[mid]), (key). тАФ , , , , :-). - . , , ┬л┬╗.
:

static int BinarySearch_Rec(int[] array, int key, int left, int right)
{
    int mid = left + (right - left) / 2;

    if (array[mid] == key)
        return mid;

    else if (array[mid] > key)
        return BinarySearch_Rec(array, key, left, mid);
    else
        return BinarySearch_Rec(array, key, mid + 1, right);
}
:

static int BinarySearch_Iter(int[] array, int key)
{
    int left = 0;
    int right = array.Length;

    while (true)
    {
        int mid = left + (right - left) / 2;

        if (array[mid] == key)
            return mid;

        if (array[mid] > key)
            right = mid;
        else
            left = mid + 1;
    }
}


:
, , , . while(true), , . , , . , .


, , . - , ? - . ? ( , -1)? int int? null? (int? c# тАФ , null). , - , ? - ? тАж , ┬л ?┬╗. , , : , . , , , null, null.

-(1 + left), , , , . , тАФ , . DRY, - , . , .

, left == right, .., тАФ [left, right). , right тАФ left < 1 right тАФ left <= 0. , , , - ( , ).

:

static int BinarySearch_Rec(int[] array, int key, int left, int right)
{
    int mid = left + (right - left) / 2;

    if (left >= right)
        return -(1 + left);

    if (array[mid] == key)
        return mid;

    else if (array[mid] > key)
        return BinarySearch_Rec(array, key, left, mid);
    else
        return BinarySearch_Rec(array, key, mid + 1, right);
}
:

static int BinarySearch_Iter(int[] array, int key)
{
    int left = 0;
    int right = array.Length;
    int mid = 0;

    while (!(left >= right))
    {
        mid = left + (right - left) / 2;

        if (array[mid] == key)
            return mid;

        if (array[mid] > key)
            right = mid;
        else
            left = mid + 1;
    }

    return -(1 + left);
}


:
, . , , . , - , .

тДЦ3


, . ||, &&, , XOR':
descendingOrderarray[mid] > keyXOR
000
011
101
110

.. descendingOrder , , , . ┬л┬╗, , - . , .
:

static int BinarySearch_Rec(int[] array, bool descendingOrder, int key, int left, int right)
{
    int mid = left + (right - left) / 2;

    if (left >= right)
        return -(1 + left);

    if (array[mid] == key)
        return mid;

    else if ((array[mid] > key) ^ descendingOrder)
        return BinarySearch_Rec(array, descendingOrder, key, left, mid);
    else
        return BinarySearch_Rec(array, descendingOrder, key, mid + 1, right);
}

static int BinarySearch_Rec_Wrapper(int[] array, int key)
{
	if (array.Length == 0)
        return -1;

    bool descendingOrder = array[0] > array[array.Length - 1];
    return BinarySearch_Rec(array, descendingOrder, key, 0, array.Length);
}
:

static int BinarySearch_Iter(int[] array, bool descendingOrder, int key)
{
    int left = 0;
    int right = array.Length;
    int mid = 0;

    while (!(left >= right))
    {
        mid = left + (right - left) / 2;

        if (array[mid] == key)
            return mid;

        if ((array[mid] > key) ^ descendingOrder)
            right = mid;
        else
            left = mid + 1;
    }

    return -(1 + left);
}

static int BinarySearch_Iter_Wrapper(int[] array, int key)
{
	if (array.Length == 0)
    	return -1;

    bool descendingOrder = array[0] > array[array.Length - 1];
    return BinarySearch_Iter(array, descendingOrder, key);
}


:
: , . .

тДЦ4


, . ┬л┬╗ тАФ , . , , тАж .
, , :

, , , . , , . , , . (. )

:

static int BinarySearch_Rec(int[] array, bool descendingOrder, int key, int left, int right)
{
    int mid = left + (right - left) / 2;

    if (left >= right)
        return -(1 + left);

    if (array[left] == key)
        return left;

    if (array[mid] == key)
    {
        if (mid == left + 1)
            return mid;
        else
            return BinarySearch_Rec(array, descendingOrder, key, left, mid + 1);
    }

    else if ((array[mid] > key) ^ descendingOrder)
        return BinarySearch_Rec(array, descendingOrder, key, left, mid);
    else
        return BinarySearch_Rec(array, descendingOrder, key, mid + 1, right);
}

static int BinarySearch_Rec_Wrapper(int[] array, int key)
{
    if (array.Length == 0)
        return -1;

    bool descendingOrder = array[0] > array[array.Length - 1];
    return BinarySearch_Rec(array, descendingOrder, key, 0, array.Length);
}
:

static int BinarySearch_Iter(int[] array, bool descendingOrder, int key)
{
    int left = 0;
    int right = array.Length;
    int mid = 0;

    while (!(left >= right))
    {
        mid = left + (right - left) / 2;

        if (array[left] == key)
            return left;

        if (array[mid] == key)
        {
            if (mid == left + 1)
                return mid;
            else
                right = mid + 1;
        }

        else if ((array[mid] > key) ^ descendingOrder)
            right = mid;
        else
            left = mid + 1;
    }

    return -(1 + left);
}

static int BinarySearch_Iter_Wrapper(int[] array, int key)
{
    if (array.Length == 0)
        return -1;

    bool descendingOrder = array[0] > array[array.Length - 1];
    return BinarySearch_Iter(array, descendingOrder, key);
}


тДЦ5


, , , , . , , :
?
?

enum ElementToChoose
{
	First,
	Last,
	NoCare
}

/// <summary>
/// Finds element equal to value in sorted array in range [low, high)
/// </summary>
static int binarySearch(int value, int[] array, bool ascendingOrder, ElementToChoose elementToChoose, int low, int high) {
	// return valid invalid position
	if (low >= high)
		return -(low + 1);

	// return first or last found element
	if (elementToChoose == ElementToChoose.First)
		if (value == array[low])
			return low;

	int last = high - 1;

	if (elementToChoose == ElementToChoose.Last)
		if (value == array[last])
			return last;

	int mid = low + (high - low) / 2;

	// we have found some element
	if (value == array[mid]) {
		switch (elementToChoose) {
			case ElementToChoose.NoCare:
				return mid;

			case ElementToChoose.First:
				if (mid - low <= 1)
					// array[mid] is the earliest element in array, return it
					// because array[low] != value && array[low+1] == value, where mid == low + 1
					return mid;
				else
					// try to find first element
					// don't forget to capture current element {|0, 0|, 1} -> {0, 0}
					return binarySearch(value, array, ascendingOrder, elementToChoose, low, mid + 1);
			case ElementToChoose.Last:
				if (last - mid <= 1)
					// array[mid] is the last element in array, return it
					// because array[last] != value && array[last - 1] == value, where mid == last - 1
					return mid;
				else
					// try to find last element
					// don't forget to capture current element {0, |0, 1|} -> {0, 1}
					return binarySearch(value, array, ascendingOrder, elementToChoose, mid, high);
		}
	}

	// choose left or right half, depending on sorting order & comparing value and mid
	if ((value < array[mid]) ^ !ascendingOrder)
		return binarySearch(value, array, ascendingOrder, elementToChoose, low, mid);
	else
		return binarySearch(value, array, ascendingOrder, elementToChoose, mid + 1, high);
}

, ? , 3 , ? , , , ( ).

, , / getFirstHalf, getSecondHalf ( ), getStartPoint/getLastPoint ( / ), increaseLength/decreaseLength ( ), moveStartPoint. - . , .

, , . тАж , ┬л ┬╗, . :


//   - Func<float, float> ,  float   float
static float BinarySearch_Func(Func<float, float> func, bool descendingOrder, float key, float left, float right)
{
    float mid = (left + right) / 2;

    if (left == mid || mid == right)
        return mid;

    if ((func(mid) > key) ^ descendingOrder)
        return BinarySearch_Func(func, descendingOrder, key, left, mid);
    else
        return BinarySearch_Func(func, descendingOrder, key, mid, right);
}

static float BinarySearch_Func_Wrapper(Func<float, float> func, float key, float left, float right)
{
    if (left > right)
        return float.NaN;

    bool descendingOrder = func(left) > func(right);
    bool isOk = true;

    if (!descendingOrder)
        isOk = func(left) <= key && key <= func(right);
    else
        isOk = func(right) <= key && key <= func(left);

    if (isOk)
        return BinarySearch_Func(func, descendingOrder, key, left, right);
    else
        return float.NaN;
}

. ? ? float'? ( , ?, , - ).
? left; right? [left, right], [left, right), (left, right], (left, right)? . :

//   x => x - -  f(x) = x
Console.WriteLine(BinarySearch_Func_Wrapper(x => x, 0.7f, 0.7f, 100.0f)); // : 0.7
Console.WriteLine(BinarySearch_Func_Wrapper(x => x, 0.8f, 0.8f, 100.0f)); // : 0,8000001
Console.WriteLine(BinarySearch_Func_Wrapper(x => x, 0.9f, 0.9f, 100.0f)); // : 0,9

Console.WriteLine("{0:0.00000000}",0.8f); // : 0,80000000

, left . right (). .. a b, a, b, - . .
, , , mid /. .

- , func(left) == key func(right) == key, .

, : , .
, , - . , - .
, - , : , тАФ , a/b. : a b . -: O(lgn).

, : - тАФ , // , , ?

P.S: , . ,
P.P.S: ?

UPD1: fox_anthony -(1 + left) ~left. : ~, msdn, c#


Source: https://habr.com/ru/post/In146228/


All Articles