Start learning free

LESSON 280 OF 409 · DIVIDE AND CONQUER

Merge Sort in C++ with O(n log n) Time Complexity

Practice O(n log n) Read the full explanation

In this video lesson we will study how the Merge Sort algorithm works, we will analyze its time and space complexities and then we will implement it:


Problem - Merge Sort:

Given a vector of integers nums, sort it in ascending order using Merge Sort

Example 1:

Input: nums = [3, 1, 3, 2, 5, 4]
Output: [1, 2, 3, 3, 4, 5]

Note:

Your algorithm should run in O(n log n) time and use O(n) extra space.


STEP 1 OF 26
    Ctrl + Enter to check

    C++ · DIVIDE AND CONQUER

    Merge Sort in C++, explained

    Understanding the Problem

    The core challenge of this problem is to sort an array of integers efficiently. Merge Sort is a classic sorting algorithm that uses the divide-and-conquer strategy to achieve this. It is significant because it guarantees a time complexity of O(n log n), making it suitable for large datasets. Common applications include sorting data in databases, file systems, and more.

    Potential pitfalls include misunderstanding the recursive nature of the algorithm and mishandling the merging process, which can lead to incorrect sorting.

    Approach

    To solve this problem, we can break it down into the following steps:

    1. Divide the array into two halves.
    2. Recursively sort each half.
    3. Merge the two sorted halves into a single sorted array.

    A naive solution might involve repeatedly finding the minimum element and moving it to the front, but this would result in a time complexity of O(n^2), which is not efficient for large arrays.

    Merge Sort, on the other hand, is more efficient. It divides the array into smaller subarrays, sorts them, and then merges them back together. This approach ensures that the sorting process is efficient and scalable.

    Algorithm

    Here is a step-by-step breakdown of the Merge Sort algorithm:

    1. Divide the array into two halves.
    2. Recursively sort each half.
    3. Merge the two sorted halves by comparing elements from each half and arranging them in order.

    The merging process is crucial as it ensures that the final array is sorted. By repeatedly dividing and merging, we achieve the desired sorted array.

    Code Implementation

    
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    // Function to merge two halves
    void merge(vector<int>& nums, int left, int mid, int right) {
        int n1 = mid - left + 1;
        int n2 = right - mid;
    
        // Create temporary arrays
        vector<int> L(n1), R(n2);
    
        // Copy data to temporary arrays L[] and R[]
        for (int i = 0; i < n1; i++)
            L[i] = nums[left + i];
        for (int j = 0; j < n2; j++)
            R[j] = nums[mid + 1 + j];
    
        // Merge the temporary arrays back into nums[left..right]
        int i = 0, j = 0, k = left;
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                nums[k] = L[i];
                i++;
            } else {
                nums[k] = R[j];
                j++;
            }
            k++;
        }
    
        // Copy the remaining elements of L[], if any
        while (i < n1) {
            nums[k] = L[i];
            i++;
            k++;
        }
    
        // Copy the remaining elements of R[], if any
        while (j < n2) {
            nums[k] = R[j];
            j++;
            k++;
        }
    }
    
    // Function to implement merge sort
    void mergeSort(vector<int>& nums, int left, int right) {
        if (left >= right)
            return;
    
        int mid = left + (right - left) / 2;
    
        // Recursively sort first and second halves
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);
    
        // Merge the sorted halves
        merge(nums, left, mid, right);
    }
    
    int main() {
        vector<int> nums = {3, 1, 3, 2, 5, 4};
        mergeSort(nums, 0, nums.size() - 1);
    
        // Print the sorted array
        for (int num : nums) {
            cout << num << " ";
        }
        return 0;
    }
    

    Complexity Analysis

    The time complexity of Merge Sort is O(n log n) because the array is divided in half log n times, and the merging process takes linear time in each division. The space complexity is O(n) due to the temporary arrays used for merging.

    Compared to the naive approach, Merge Sort is significantly more efficient, especially for large datasets.

    Edge Cases

    Potential edge cases include:

    • An empty array: The algorithm should handle this gracefully and return an empty array.
    • An array with one element: The algorithm should return the array as is.
    • An array with duplicate elements: The algorithm should correctly sort and include all duplicates.

    Testing these edge cases ensures the robustness of the algorithm.

    Testing

    To test the solution comprehensively, consider the following test cases:

    • Simple cases: [3, 1, 3, 2, 5, 4]
    • Edge cases: [], [1], [2, 1]
    • Large arrays: Generate large arrays with random values to test performance.

    Using a testing framework like Google Test can help automate and manage these tests effectively.

    Thinking and Problem-Solving Tips

    When approaching such problems, consider the following tips:

    • Understand the problem requirements and constraints thoroughly.
    • Break down the problem into smaller, manageable parts.
    • Consider different approaches and analyze their time and space complexities.
    • Practice solving similar problems to improve your problem-solving skills.

    Conclusion

    Merge Sort is a powerful and efficient sorting algorithm that guarantees a time complexity of O(n log n). Understanding and implementing this algorithm is crucial for solving sorting problems effectively. By practicing and exploring further, you can enhance your problem-solving skills and tackle more complex challenges.

    Additional Resources

    For further reading and practice, consider the following resources:

    Keep going with C++About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free