Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Binary Search and Element Removal Techniques in C++

Tools May 8 4

Binary Search (LeetCode 704)

Binary search requires the input array to be sorted and typically contains unique elements to ensure the result is unambiguous. The algorithm reduces the search space by comparing the target with the middle element of the currrent interval.

Approach 1: Closed Interval [left, right]

In this approach, left and right represent the actual first and last indices. Since the interval is inclusive, the loop continues as long as left <= right.

class Solution {
public:
    int search(vector<int>& arr, int key) {
        int start = 0;
        int end = arr.size() - 1;

        while (start <= end) {
            // Calculate mid to avoid potential overflow from (start + end)
            int mid = start + (end - start) / 2;

            if (arr[mid] > key) {
                end = mid - 1; // Target is in the left half
            } else if (arr[mid] < key) {
                start = mid + 1; // Target is in the right half
            } else {
                return mid; // Target found
            }
        }
        return -1; // Target not found
    }
};

Approach 2: Half-Open Interval [left, right)

Here, right represents the index just past the last element. Consequently, left == right is a invalid empty range, so the loop condition is left < right.

class Solution {
public:
    int search(vector<int>& arr, int key) {
        int start = 0;
        int end = arr.size(); 

        while (start < end) {
            int mid = start + ((end - start) >> 1); // Using right shift for division by 2

            if (arr[mid] > key) {
                end = mid; // Narrow down to [start, mid)
            } else if (arr[mid] < key) {
                start = mid + 1; // Narrow down to [mid + 1, end)
            } else {
                return mid;
            }
        }
        return -1;
    }
};

Remove Element (LeetCode 27)

Brute Force

A naive solution involves two nested loops. When the target value is found, shift all subsequent elements forward. This results in a time complexity of $O(n^2)$.

Optimized Approach: Two Pointers

Single Direction (Slow/Fast)

This method maintains the relative order of elements. The fast pointer explores the array, while the slow pointer writes valid elements.

class Solution {
public:
    int removeElement(vector<int>& data, int target) {
        int writeIdx = 0;
        for (int readIdx = 0; readIdx < data.size(); ++readIdx) {
            if (data[readIdx] != target) {
                data[writeIdx] = data[readIdx];
                ++writeIdx;
            }
        }
        return writeIdx;
    }
};

Opposing Directions

This approach swaps elements to minimize movements. It is efficient when the number of elements to remove is small, though it changes the original order.

class Solution {
public:
    int removeElement(vector<int>& data, int target) {
        int front = 0;
        int back = data.size() - 1;

        while (front <= back) {
            // Advance front until we find the target value
            while (front <= back && data[front] != target) {
                ++front;
            }
            // Move back until we find a non-target value
            while (front <= back && data[back] == target) {
                --back;
            }
            // Swap or overwrite
            if (front < back) {
                data[front] = data[back];
                ++front;
                --back;
            }
        }
        return front;
    }
};

Complexity Reference

When evaluating algorithm efficeincy, common time complexities rank as follows: $O(\log n) < O(n) < O(n \log n) < O(n^2)$. Solutions often return the result directly to the caller without standard input/output handling in the function itself.

Tags: C++

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Installing CocoaPods on macOS Catalina (10.15) Using a User-Managed Ruby

System Ruby on macOS 10.15 frequently fails to build native gems required by CocoaPods (for example, ffi), leading to errors like: ERROR: Failed to build gem native extension checking for ffi.h... no...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.