|
| 1 | +--- |
| 2 | +id: find-first-and-last-position-of-element-in-sorted-array |
| 3 | +title: Find First and Last Position of Element in Sorted Array(LeetCode) |
| 4 | +sidebar_label: 0034-Find First and Last Position of Element in Sorted Array |
| 5 | +tags: |
| 6 | + - Array |
| 7 | + - Binary Search |
| 8 | +description: Given an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value. |
| 9 | +sidebar_position: 34 |
| 10 | +--- |
| 11 | + |
| 12 | +## Problem Statement |
| 13 | + |
| 14 | +Given an array of integers `nums` sorted in non-decreasing order, find the starting and ending position of a given `target` value. |
| 15 | + |
| 16 | +If `target` is not found in the array, return [-1, -1]. |
| 17 | + |
| 18 | +You must write an algorithm with O(log n) runtime complexity. |
| 19 | + |
| 20 | +### Examples |
| 21 | + |
| 22 | +**Example 1:** |
| 23 | + |
| 24 | +```plaintext |
| 25 | +Input: nums = [5,7,7,8,8,10], target = 8 |
| 26 | +Output: [3,4] |
| 27 | +``` |
| 28 | + |
| 29 | +**Example 2:** |
| 30 | + |
| 31 | +```plaintext |
| 32 | +Input: nums = [5,7,7,8,8,10], target = 6 |
| 33 | +Output: [-1,-1] |
| 34 | +``` |
| 35 | + |
| 36 | +**Example 3:** |
| 37 | + |
| 38 | +```plaintext |
| 39 | +Input: nums = [], target = 0 |
| 40 | +Output: [-1,-1] |
| 41 | +``` |
| 42 | + |
| 43 | +### Constraints |
| 44 | + |
| 45 | +- `0 <= nums.length <= 105` |
| 46 | +- `109 <= nums[i] <= 109` |
| 47 | +- `nums` is a non-decreasing array. |
| 48 | +- `109 <= target <= 109` |
| 49 | + |
| 50 | +## Solution |
| 51 | + |
| 52 | +When solving the problem of finding the starting and ending position of a target value in a sorted array, we can use |
| 53 | +two main approaches: Linear Search (Brute Force) and Binary Search (Optimized). Below, both approaches are explained along with their time and space complexities. |
| 54 | + |
| 55 | +### Approach 1: Linear Search (Brute Force) |
| 56 | + |
| 57 | +#### Explanation: |
| 58 | + |
| 59 | +1. Traverse the array from the beginning to find the first occurrence of the target. |
| 60 | +2. Traverse the array from the end to find the last occurrence of the target. |
| 61 | +3. Return the indices of the first and last occurrences. |
| 62 | + |
| 63 | +#### Algorithm |
| 64 | + |
| 65 | +1. Initialize `startingPosition` and `endingPosition` to -1. |
| 66 | +2. Loop through the array from the beginning to find the first occurrence of the target and set `startingPosition`. |
| 67 | +3. Loop through the array from the end to find the last occurrence of the target and set `endingPosition`. |
| 68 | +4. Return `{startingPosition, endingPosition}`. |
| 69 | + |
| 70 | +#### Implementation |
| 71 | + |
| 72 | +```C++ |
| 73 | +class Solution { |
| 74 | +public: |
| 75 | + vector<int> searchRange(vector<int>& nums, int target) { |
| 76 | + int startingPosition = -1, endingPosition = -1; |
| 77 | + int n = nums.size(); |
| 78 | + for(int i = 0; i < n; i++) { |
| 79 | + if(nums[i] == target) { |
| 80 | + startingPosition = i; |
| 81 | + break; |
| 82 | + } |
| 83 | + } |
| 84 | + for(int i = n - 1; i >= 0; i--) { |
| 85 | + if(nums[i] == target) { |
| 86 | + endingPosition = i; |
| 87 | + break; |
| 88 | + } |
| 89 | + } |
| 90 | + return {startingPosition, endingPosition}; |
| 91 | + } |
| 92 | +}; |
| 93 | +``` |
| 94 | +
|
| 95 | +### Complexity Analysis |
| 96 | +
|
| 97 | +- **Time complexity**: O(N), where N is the size of the array. In the worst case, we might traverse all elements of the array. |
| 98 | +- **Space complexity**: O(1), as we are using a constant amount of extra space. |
| 99 | +
|
| 100 | +### Approach 2: Binary Search (Optimized) |
| 101 | +
|
| 102 | +#### Explanation: |
| 103 | +
|
| 104 | +1. Use binary search to find the lower bound (first occurrence) of the target. |
| 105 | +2. Use binary search to find the upper bound (last occurrence) of the target by searching for the target + 1 and subtracting 1 from the result. |
| 106 | +3. Check if the target exists in the array and return the indices of the first and last occurrences. |
| 107 | +
|
| 108 | +#### Algorithm |
| 109 | +
|
| 110 | +1. Define a helper function `lower_bound` to find the first position where the target can be inserted. |
| 111 | +2. Use `lower_bound` to find the starting position of the target. |
| 112 | +3. Use `lower_bound` to find the position where `target + 1` can be inserted, then subtract 1 to get the ending position. |
| 113 | +4. Check if `startingPosition` is within bounds and equals the target. |
| 114 | +5. Return `{startingPosition, endingPosition}` if the target is found, otherwise return `{-1, -1}`. |
| 115 | +
|
| 116 | +#### Implementation (First Version) |
| 117 | +
|
| 118 | +```C++ |
| 119 | +class Solution { |
| 120 | +private: |
| 121 | + int lower_bound(vector<int>& nums, int low, int high, int target) { |
| 122 | + while(low <= high) { |
| 123 | + int mid = (low + high) >> 1; |
| 124 | + if(nums[mid] < target) { |
| 125 | + low = mid + 1; |
| 126 | + } else { |
| 127 | + high = mid - 1; |
| 128 | + } |
| 129 | + } |
| 130 | + return low; |
| 131 | + } |
| 132 | +public: |
| 133 | + vector<int> searchRange(vector<int>& nums, int target) { |
| 134 | + int low = 0, high = nums.size() - 1; |
| 135 | + int startingPosition = lower_bound(nums, low, high, target); |
| 136 | + int endingPosition = lower_bound(nums, low, high, target + 1) - 1; |
| 137 | + if(startingPosition < nums.size() && nums[startingPosition] == target) { |
| 138 | + return {startingPosition, endingPosition}; |
| 139 | + } |
| 140 | + return {-1, -1}; |
| 141 | + } |
| 142 | +}; |
| 143 | +``` |
| 144 | +#### Implementation (Second Version) |
| 145 | + |
| 146 | +```C++ |
| 147 | +class Solution { |
| 148 | +public: |
| 149 | + vector<int> searchRange(vector<int>& nums, int target) { |
| 150 | + int startingPosition = lower_bound(nums.begin(), nums.end(), target) - nums.begin(); |
| 151 | + int endingPosition = lower_bound(nums.begin(), nums.end(), target + 1) - nums.begin() - 1; |
| 152 | + if(startingPosition < nums.size() && nums[startingPosition] == target) { |
| 153 | + return {startingPosition, endingPosition}; |
| 154 | + } |
| 155 | + return {-1, -1}; |
| 156 | + } |
| 157 | +}; |
| 158 | +``` |
| 159 | +
|
| 160 | +### Complexity Analysis |
| 161 | +
|
| 162 | +- **Time complexity**: O(log N), where N is the size of the array. We perform binary search, which has a logarithmic time complexity. |
| 163 | +- **Space complexity**: O(1), as we are using a constant amount of extra space. |
| 164 | +
|
| 165 | +### Conclusion |
| 166 | +
|
| 167 | +1. Linear Search is straightforward but less efficient with a time complexity of O(N). |
| 168 | +2. Binary Search is more efficient with a time complexity of O(log N), making it suitable for large datasets. |
| 169 | +Both approaches provide a clear way to find the starting and ending positions of a target value in a sorted array, with the Binary Search approach being the |
| 170 | +optimized solution. |
0 commit comments