diff --git a/.github/workflows/code-format.yml b/.github/workflows/code-format.yml index 4276ff7..5abe714 100644 --- a/.github/workflows/code-format.yml +++ b/.github/workflows/code-format.yml @@ -5,8 +5,6 @@ on: push: - pull_request: - jobs: format: runs-on: ubuntu-latest diff --git a/Algorithms/Searching-Algorithms/Binary-Search/01-lower&upper-bound.md b/Algorithms/Searching-Algorithms/Binary-Search/01-lower&upper-bound.md new file mode 100644 index 0000000..7fbecea --- /dev/null +++ b/Algorithms/Searching-Algorithms/Binary-Search/01-lower&upper-bound.md @@ -0,0 +1,115 @@ +## Find Lower and Upper bound in an array. + +### Lower Bound : + +If we have a sorted array `arr` and a target element `x` which is supposed to be found in that array, then a Lower bound is the **Smallest** `index` in that array such that, + +```cpp +arr[index] >= x; +``` + +--- + +**Example :** + +```cpp +int arr[6] = {1, 2, 4, 4, 5, 7}; +int x = 4; // element to be found in array +``` + +If we iterate over the array, we can find that 4 >= 4, 4 >= 4, 5 >= 4 and 7 >= 4. But the first occurence of 4 at index 2 satisfies the condition as it is `>=` the target element and it's index is the smallest of all. + +**Hence, The Lower bound of this array is 2.** + +--- + +### Upper Bound : + +If we have a sorted array `arr` and a target element `x` which is supposed to be found in that array, then an Upper bound is the **Smallest** `index` in that array such that, + +```cpp +arr[index] > x; // note the sign here +``` + +--- + +**Example :** + +```cpp +int arr[6] = {1, 2, 4, 4, 5, 7}; +int x = 4; // element to be found in array +``` + +If we iterate over the array, we can find that 5 > 4 and 7 > 4. But the value 5 at index 4 satisfies the condition as it is `>` the target element and it's index is the smallest of all. + +**Hence, The upper bound of this array is 4.** + +--- + +**Note :** There could be an edge case where no such target element exists or which satisfies `arr[index] >= target` or `arr[index] > target`, then we will return the nth element of the array because, then it would the hypothetical lower or upper bound for that array. + +**Example :** + +```cpp +int arr[6] = {1, 2, 4, 4, 5, 7}; +int x = 7; +/* +this x value would have upper bound == 6, +as no element is > than 7 +*/ +``` + +--- + +**Implementation :** + +```cpp +#include +using namespace std; + +int lowerBound(int* arr, int n, int x){ + int low = 0, high = n - 1; + int ans = n; // edge case + while (low <= high){ + int mid = (low + (high - low)) / 2; + // maybe answer + if (arr[mid] >= x){ + ans = mid; + // look for more small index in left + high = mid - 1; + } else { + low = mid + 1; // look for right + } + } + return ans; +} + +int upperBound(int* arr, int n, int x){ + int low = 0, high = n - 1; + int ans = n; + while (low <= high){ + int mid = (low + (high - low)) / 2; + // maybe answer + if (arr[mid] > x){ + ans = mid; + // look for more small index in left + high = mid - 1; + } else { + low = mid + 1; // look for right + } + } + return ans; +} + +int main(){ + int n; cin >> n; + int arr[n]; + for (int i = 0; i < n; i++>){ + cin >> arr[i]; + } + int x; cin >> x; + cout << "Lower Bound : " << lowerBound(arr, n, x); + cout << "Upper Bound : " << upperBound(arr, n, x); + return 0; +} +``` diff --git a/Algorithms/Searching-Algorithms/Binary-Search/binary-search.md b/Algorithms/Searching-Algorithms/Binary-Search/binary-search.md new file mode 100644 index 0000000..06c4ce9 --- /dev/null +++ b/Algorithms/Searching-Algorithms/Binary-Search/binary-search.md @@ -0,0 +1,117 @@ +# Binary Search. + +_Search Element in a Linear **Sorted** Data Structure._ + +**Time Complexity:** + +1. Best Case: O(1) --> Element at middle of the array. +2. Average / Worst Case: O(log n) --> Element at 1st or last position. + +## Logic. + +1. Find Mid --> mid = start + (end - start) / 2. +2. Compare mid with target --> possible comparisons (mid == target) or (mid > target) or (mid < target). +3. If mid == target, return mid. +4. If mid != target, change path w.r.t (mid > target) or (mid < target) +5. If mid > target, start --> same, end --> mid - 1. +6. If mid < target, end --> same, start --> mid + 1. +7. Repeat. + +## Implementation 1 - Iterative Approach + +```cpp +#include +using namespace std; + +int binarySearch(int *arr, int size, int target) { + int start = 0; + int end = size - 1; + int mid = start + (end - start) / 2; + while (start <= end) + { + if (arr[mid] == target) + return mid; + if (arr[mid] > target) + end = mid - 1; + else + start = mid + 1; + mid = start + (end - start) / 2; + } + return -1; +} + +int main() { + int arr[5] = {1, 2, 3, 4, 5}; + int index = binarySearch(arr, 5, 3); + if (index == -1) + cout << "NOT FOUND!"; + else + cout << "Element found at Index " << index; + return 0; +} + +``` + +--- + +## Implementation 2 - Recursive Approach + +```cpp +#include +using namespace std; + +int binarySearch(vector&arr, int low, int high, int target) { + + // base case + if (low > high) return -1; + + // calculate mid + int mid = low + (high - low) / 2; + + // if found, return mid index + if (arr[mid] == target) return mid; + + // if target > arr[mid], call the binarySearch function with updated low index. + else if (target > arr[mid]) return binarySearch(arr, mid+1, high, target); + + // else when target < arr[mid], call the binarySearch function with updated high index. + return binarySearch(arr, low, mid-1, target); +} + +int search(vector&nums, int target){ + return binarySearch(nums, 0, nums.size() - 1, target); +} + +int main() { + int vectorarr = {1, 2, 3, 4, 5}; + int index = search(arr, 5, 3); + if (index == -1) + cout << "NOT FOUND!"; + else + cout << "Element found at Index " << index; + return 0; +} + +``` + +## Linear Search v/s Binary Search. + +In Linear search, for the worst case, if the size of array is 1000, then the function will perform 1000 comparisons. +In Binary Search, for worst case, for 1000 size array, the function will perform log2(1000) = 10 comparisons, +which is 100 times less than Linear Search. + +## How O(log n) ? + +Suppose a N sized array perform binary search, then the middle element will be at N/21 position where 1 represents 1st comparison. + +The next mid will be at N/22 Position where 2 represents 2nd comparison. + +Similarly at last comparison, N/2k , the mid = size of array i.e, 1. + +Therefore N/2k = 1 + +N = 2k + +Log2N = K + +Which means, at kth comparison, the size of array will be log2N diff --git a/Algorithms/Sliding-Window/02-problem-1.md b/Algorithms/Sliding-Window/02-problem-1.md index 1850e34..a9a4d0d 100644 --- a/Algorithms/Sliding-Window/02-problem-1.md +++ b/Algorithms/Sliding-Window/02-problem-1.md @@ -32,7 +32,7 @@ Return an integer which is maximum sum among all the sub-arrays. **Identificaion :** -We are given with an **array/string**, we're asked for a **sub-array/substring** and either we have a window size [**fixed size window**] or a condition for window size [**variable size window**]. +We are given with an **array/string**, we're asked for a **subarray/substring** and either we have a window size [**fixed size window**] or a condition for window size [**variable size window**]. ---