Posted on

LeetCode 543 Diameter of a Binary Tree in C++

Given the root of a binary tree, return the length of the diameter of the tree.

The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.

The length of a path between two nodes is represented by the number of edges between them.

Example 1:
Input: root = [1,2,3,4,5] Output: 3
Explanation: 3 is the length of the path [4,2,1,3] or [5,2,1,3].


Example 2:
Input: root = [1,2] Output: 1

Constraints:

-100 <= Node.val <= 100

The number of nodes in the tree is in the range [1, 104].

Solution in C++ with a test case:


#include <iostream>
#include <algorithm>
using namespace std;

// Definition for a binary tree node.
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    int result;
    int dfs(TreeNode* root) {
        if (root == nullptr) return 0;
        int left = dfs(root->left);
        int right = dfs(root->right);
        result = max(result, left + right);
        return max(left, right) + 1;
    }

    int diameterOfBinaryTree(TreeNode* root) {
        result = 0;
        dfs(root);
        return result;
    }
};

// Helper function to create a tree
TreeNode* createTree() {
    /*
        Example tree:
                1
               / \
              2   3
             / \
            4   5
    */
    TreeNode* root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->left->right = new TreeNode(5);
    return root;
}

int main() {
    // Create a sample binary tree
    TreeNode* root = createTree();

    // Create a Solution object
    Solution solution;

    // Call the diameterOfBinaryTree function
    int diameter = solution.diameterOfBinaryTree(root);

    // Output the result
    cout << "Diameter of the binary tree: " << diameter << endl;

    // Clean up memory (optional but good practice)
    delete root->left->left;
    delete root->left->right;
    delete root->left;
    delete root->right;
    delete root;

    return 0;
}
Posted on

401. Binary Watch

A binary watch has 4 LEDs on the top to represent the hours (0-11), and 6 LEDs on the bottom to represent the minutes (0-59). Each LED represents a zero or one, with the least significant bit on the right.

  • For example, the below binary watch reads "4:51".

Given an integer turnedOn which represents the number of LEDs that are currently on (ignoring the PM), return all possible times the watch could represent. You may return the answer in any order.

The hour must not contain a leading zero.

  • For example, "01:00" is not valid. It should be "1:00".

The minute must consist of two digits and may contain a leading zero.

  • For example, "10:2" is not valid. It should be "10:02".

Example 1:

Input: turnedOn = 1
Output: ["0:01","0:02","0:04","0:08","0:16","0:32","1:00","2:00","4:00","8:00"]

Example 2:

Input: turnedOn = 9
Output: []

Solution

import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<String> readBinaryWatch(int turnedOn) {
        List<String> result = new ArrayList<>();

        // Iterate over possible hours (0 to 11)
        for (int hour = 0; hour < 12; hour++) {
            // Iterate over possible minutes (0 to 59)
            for (int minute = 0; minute < 60; minute++) {
                // Count the number of bits turned on
                int bitsOn = Integer.bitCount(hour) + Integer.bitCount(minute);
                
                // If the total bits on matches the turnedOn count
                if (bitsOn == turnedOn) {
                    // Format the time as "H:MM"
                    result.add(String.format("%d:%02d", hour, minute));
                }
            }
        }
        return result;
    }
}
Posted on

Letter Combinations of a phone number

Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.

A mapping of digits to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

Example 1:

Input: digits = "23"
Output: ["ad","ae","af","bd","be","bf","cd","ce","cf"]

Example 2:

Input: digits = ""
Output: []

Example 3:

Input: digits = "2"
Output: ["a","b","c"]

Java Solution

class Solution {
     public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) {
            return new ArrayList<>();
        }
        Map<Character, String> digitToLetters = new HashMap<>();
        digitToLetters.put('2', "abc");
        digitToLetters.put('3', "def");
        digitToLetters.put('4', "ghi");
        digitToLetters.put('5', "jkl");
        digitToLetters.put('6', "mno");
        digitToLetters.put('7', "pqrs");
        digitToLetters.put('8', "tuv");
        digitToLetters.put('9', "wxyz");

        List<String> result = new ArrayList<>();
        backtrack(digits, 0, new StringBuilder(), result, digitToLetters);
        return result;
    }

    private void backtrack(String digits, int index, StringBuilder path, List<String> result, Map<Character, String> digitToLetters) {
        if (index == digits.length()) {
            result.add(path.toString());
            return;
        }

        char digit = digits.charAt(index);
        String letters = digitToLetters.get(digit);
        for (char letter : letters.toCharArray()) {
            path.append(letter);
            backtrack(digits, index + 1, path, result, digitToLetters);
            path.deleteCharAt(path.length() - 1);
        }
    }
}

C++ Solution

//
// Created by robert on 12/20/24.
//
#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;
void backtrack(string & digits, const int index, string & current, vector<string> & result, const unordered_map<char,string> & map) {
if (digits.length() == index) {
result.push_back(current);
return;
}
char digit = digits[index];
string letters = map.find(digit)->second;
for( char letter : letters ) {
current.push_back(letter);
backtrack( digits, index+1, current, result, map );
current.pop_back();
}

}
vector<string> letterCombinations(string digits) {
vector<string> result;
string current;

if (digits.empty()) return result;

unordered_map<char, string> map;

map.insert(make_pair('2', "abc"));
map.insert(make_pair('3', "def"));
map.insert(make_pair('4', "ghi"));
map.insert(make_pair('5', "jkl"));
map.insert(make_pair('6', "mno"));
map.insert(make_pair('7', "pqrs"));
map.insert(make_pair('8', "tuv"));
map.insert(make_pair('9', "wxyz"));


backtrack(digits, 0, current, result, map);
return result;

}

int main(){
vector<string> result = letterCombinations("23");
for (const auto & i : result) {
cout << i << endl;
}
}
Posted on

LeetCode 20 Valid Parentheses in Typescript

The mental challenge one might experience here is that JavaScript doesn’t have abstract data structures like stacks and queues built into the language. Implementations of those structures use an array underneath. So solving this problem is just as easy in TypeScript as it is in C++ with a stack. The problem is defined as:

Given a string s containing just the characters '('')''{''}''[' and ']', determine if the input string is valid.

An input string is valid if:

  1. Open brackets must be closed by the same type of brackets.
  2. Open brackets must be closed in the correct order.
  3. Every close bracket has a corresponding open bracket of the same type.

Example 1: Input: s = “()” Output: true

Example 2: Input: s = “()[]{}” Output: true

Example 3: Input: s = “(]” Output: false

Example 4: Input: s = “([])” Output: true

Solution:

function isValid(s: string): boolean {
    
    const st:string[] = [];
    for( const c of s){
        
        if( c === '(' || c === '[' || c === '{'){
            st.push(c);
        } else {
            const last =  st[st.length - 1];
            if( c === '(' && last === ')') st.pop();
            else if( c === '[' && last === ']') st.pop();
            else if( c === '{' && last === '}') st.pop();
            else st.push(c);
        }

        
    }
    
    return st.length === 0;
};

Posted on

 Max Chunks To Make Sorted

You are given an integer array arr of length n that represents a permutation of the integers in the range [0, n - 1].

We split arr into some number of chunks (i.e., partitions), and individually sort each chunk. After concatenating them, the result should equal the sorted array.

Return the largest number of chunks we can make to sort the array.

Example 1:

Input: arr = [4,3,2,1,0]
Output: 1
Explanation:
Splitting into two or more chunks will not return the required result.
For example, splitting into [4, 3], [2, 1, 0] will result in [3, 4, 0, 1, 2], which isn't sorted.

Example 2:

Input: arr = [1,0,2,3,4]
Output: 4
Explanation:
We can split into two chunks, such as [1, 0], [2, 3, 4].
However, splitting into [1, 0], [2], [3], [4] is the highest number of chunks possible.

Solution

The core idea behind the solution is to identify contiguous subsequences within the array A where the elements form a consecutive sequence starting from 0.

We iterate through the array, keeping track of the current chunk’s starting index. As long as the current element matches its index, we continue iterating. Once we encounter an element that doesn’t match its index, we’ve reached the end of the current chunk. We then append this chunk to a list of chunks and start the process again from the next element.

//
// Created by robert on 12/18/24.
//
#include <vector>
#include <iostream>

using namespace std;

int maxChunksToSorted(const vector<int>& arr) {
int chunks = 0, i =0;;

while(i < arr.size()){
int start = i;
int max_val = arr[start];
while( i < arr.size() && max_val >= i ){
max_val = max(max_val, arr[i]);
++i;
}
++chunks;
}

return chunks;
}

vector<vector<int>> findChunks(const vector<int>& arr) {
int i =0;
vector<vector<int>> chunks;
while(i < arr.size()){
int start = i;
int max_val = arr[start];
while( i < arr.size() && max_val >= i ){
max_val = max(max_val, arr[i]);
++i;
}
chunks.emplace_back(vector<int>(arr.begin() + start, arr.begin() + i));
}

return chunks;
}

void printChunks(const vector<int>& arr) {
vector<vector<int> > chunks = findChunks(arr);
cout << "[";
for (size_t i = 0; i < chunks.size(); ++i) {
cout << "[";
for (size_t j = 0; j < chunks[i].size(); ++j) {
cout << chunks[i][j];
if (j != chunks[i].size() - 1) cout << ",";
}
cout << "]";
if (i != chunks.size() - 1) cout << ",";
}
cout << "]" << endl;

}

int main(int argc, char *argv[]) {
cout << maxChunksToSorted({4,3,2,1,0}) << endl;
cout << maxChunksToSorted({1,0,2,3,4}) << endl;
cout << maxChunksToSorted({1,0, 2,3,4,5}) << endl;

printChunks({1, 0, 2, 3, 4});
printChunks({4, 3, 1, 2, 0});
printChunks({1, 0, 3, 2, 4});
printChunks({ 1, 2, 3, 4, 5, 0});
printChunks({0, 1, 2, 3, 10, 11, 12});
return 0;
}

/home/robert/CLionProjects/untitled/maxChunksToSorted
1
4
5
[[1,0],[2],[3],[4]]
[[4,3,1,2,0]]
[[1,0],[3,2],[4]]
[[1,2,3,4,5,0]]
[[0],[1],[2],[3],[10,11,12]]

Process finished with exit code 0

Posted on

Final Prices With a Special Discount in a Shop

You are given an integer array prices where prices[i] is the price of the i<sup>th</sup> item in a shop.

There is a special discount for items in the shop. If you buy the i<sup>th</sup> item, then you will receive a discount equivalent to prices[j] where j is the minimum index such that j > i and prices[j] <= prices[i]. Otherwise, you will not receive any discount at all.

Return an integer array answer where answer[i] is the final price you will pay for the i<sup>th</sup> item of the shop, considering the special discount.

Example 1:

Input: prices = [8,4,6,2,3]
Output: [4,2,4,2,3]
Explanation: 
For item 0 with price[0]=8 you will receive a discount equivalent to prices[1]=4, therefore, the final price you will pay is 8 - 4 = 4.
For item 1 with price[1]=4 you will receive a discount equivalent to prices[3]=2, therefore, the final price you will pay is 4 - 2 = 2.
For item 2 with price[2]=6 you will receive a discount equivalent to prices[3]=2, therefore, the final price you will pay is 6 - 2 = 4.
For items 3 and 4 you will not receive any discount at all.

Example 2:

Input: prices = [1,2,3,4,5]
Output: [1,2,3,4,5]
Explanation: In this case, for all items, you will not receive any discount at all.

Example 3:

Input: prices = [10,1,1,6]
Output: [9,0,1,6]

// Monotonic stack to keep track of indices
// While the stack is not empty and the current price is less than or equal
// to the price at the index stored at the top of the stack
// Apply the discount
// Push the current index onto the stack
// Return the modified answer vector

class Solution {
public:
    // vector<int> finalPrices(vector<int>& prices) {
    //     uint16_t size =  prices.size();
        
    //     for( uint16_t i = 0; i < size; i++ ){
    //         for( uint16_t j = i+1; j < size; j++ ){
    //             if(prices[i]>=prices[j]){
    //                 prices[i]-= prices[j];
    //                 break;
    //             }
    //         }
    //     }
        
    //     return prices;
    // }

    
    vector<int> finalPrices(vector<int>& prices) {
        
        stack<int> st; 
        
        for (int i = 0; i < prices.size(); i++) {
  
            while (!st.empty() && prices[i] <= prices[st.top()]) {
                int index = st.top(); 
                st.pop();
                prices[index] -= prices[i]; 
            }
            st.push(i); 
        }
        
        return prices; 
    }

};

Explanation:

  1. Monotonic Stack:
    • We use a stack to keep track of indices where the discount is yet to be applied.
    • The stack is monotonic decreasing, meaning it stores indices of prices in decreasing order of their values.
  2. Efficient Discount Calculation:
    • For each price, check the stack:
      • If the current price is less than or equal to the price at the top of the stack, apply the discount for the index at the top of the stack.
      • Remove that index from the stack since the discount has been applied.
    • Push the current index onto the stack.
  3. Time Complexity:
    • Each element is pushed onto the stack once and popped from the stack once, resulting in O(n)O(n)O(n) time complexity.

Example Execution:

For prices = [8, 4, 6, 2, 3]:

  • Initialization: answer = [8, 4, 6, 2, 3], stack = [].
  • Iteration 1 (i = 0): stack = [0].
  • Iteration 2 (i = 1):
    • prices[1] = 4 <= prices[stack.top()] = 8.
    • Apply discount: answer[0] = 8 - 4 = 4. Pop stack. stack = [].
    • Push i = 1: stack = [1].
  • Iteration 3 (i = 2): stack = [1, 2] (no discount applied yet).
  • Iteration 4 (i = 3):
    • prices[3] = 2 <= prices[stack.top()] = 6.
    • Apply discount: answer[2] = 6 - 2 = 4. Pop stack. stack = [1].
    • prices[3] = 2 <= prices[stack.top()] = 4.
    • Apply discount: answer[1] = 4 - 2 = 2. Pop stack. stack = [].
    • Push i = 3: stack = [3].
  • Iteration 5 (i = 4): stack = [3, 4] (no discount applied yet).

Final answer = [4, 2, 4, 2, 3].

Space Complexity:

  • The stack stores at most nnn indices, so the space complexity is O(n)O(n)O(n).
Posted on

C++ Solution for Generate Parentheses Leetcode Problem #22

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

Example 1:

Input: n = 3
Output: ["((()))","(()())","(())()","()(())","()()()"]

Example 2:

Input: n = 1
Output: ["()"]

Solution:

#include <string>
#include <vector>
#include <iostream>
#include <functional> // Include this for std::function

using namespace std;

vector<string> generateParenthesis(int n) {
vector<string> solutions;

// Explicitly declare the lambda with std::function
function<void(string, int, int)> backtrack = [&](const string& current, int open, int close) {
if (current.length() == n * 2) {
solutions.push_back(current);
return;
}
if (open < n) {
backtrack(current + '(', open + 1, close);
}
if (close < open) {
backtrack(current + ')', open, close + 1);
}
};

// Start the backtracking
backtrack("", 0, 0);

return solutions;
}

// Main function
int main() {
int n = 3; // Example input
vector<string> result = generateParenthesis(n);
cout << "Number of solutions: " << result.size() << endl;
// Print the results
for (const auto &str: result) {
cout << str << endl;
}

return 0;
}

Main Takeaways

You have to start with an open parentheses. So the logic reads to add open parentheses until all of them are exhausted. Then you actually start backtracking and adding a closing parentheses. So for n=2 you get a simple tree like this one below. Watch the video if you need more understanding on how to solve this one.

      o
     /
    /
   (
  / \
 /   \
((    ()
 |    |
(()) ()()
Posted on

Final Array State After K Multiplication Operations

You are given an integer array nums, an integer k, and an integer multiplier.

You need to perform k operations on nums. In each operation:

  • Find the minimum value x in nums. If there are multiple occurrences of the minimum value, select the one that appears first.
  • Replace the selected minimum value x with x * multiplier.

Return an integer array denoting the final state of nums after performing all k operations.

Approach Using a Min-Heap

We use a priority queue (min-heap) that stores pairs (value, index) to efficiently find the smallest number in the array along with its index.

Steps:

  1. Push all elements of nums into the min-heap. Each element is stored as a tuple (value, index) (to preserve the index).
  2. Perform k operations:
    • Extract the smallest element (top of the heap) from the min-heap.
    • Update the value at the extracted index in nums by multiplying it with multiplier.
    • Push the updated value (new_value, index) back into the heap.
  3. After all k operations, return the modified nums array.

Priority Queue Configuration:

  • Since we want to retrieve the smallest element, we configure priority_queue to behave as a min-heap using greater<tuple<int, int>>.
#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
using namespace std;

vector<int> getFinalState(vector<int>& nums, int k, int multiplier) {
    // Min-heap to store pairs of (value, index)
    priority_queue<tuple<int, int>, vector<tuple<int, int>>, greater<tuple<int, int>>> minHeap;

    // Step 1: Push all elements into the min-heap
    for (int i = 0; i < nums.size(); i++) {
        minHeap.push({nums[i], i});
    }

    // Step 2: Perform k operations
    for (int i = 0; i < k; i++) {
        // Extract the smallest element from the min-heap
        auto [value, index] = minHeap.top(); // Get the top element (smallest)
        minHeap.pop(); // Remove it from the heap

        // Update the value in the original array
        nums[index] = value * multiplier;

        // Push the updated value back into the min-heap
        minHeap.push({nums[index], index});
    }

    // Step 3: Return the modified array
    return nums;
}

int main() {
    vector<int> nums = {2, 3, 1, 5, 1}; // Example array
    int k = 2;                          // Number of operations
    int multiplier = 4;                 // Multiplier

    vector<int> result = getFinalState(nums, k, multiplier);

    // Output the result
    for (int num : result) {
        cout << num << " ";
    }

    return 0;
}

Explanation of the Code:

  1. Heap Initialization:
    • All elements in nums are pushed into the min-heap along with their respective indices. This ensures that when we extract the minimum element, we also know its index in the original array.
  2. Perform k Operations:
    • For each operation, the smallest value from the heap is fetched (using minHeap.top()).
    • This value is updated (multiplied by multiplier) in the nums array.
    • The updated value, along with the same index, is reinserted into the heap to maintain the order of elements.
  3. Final State:
    • After k operations, the array nums is modified, and we return it.

Complexity Analysis:

  1. Time Complexity:
    • Building the initial heap: O(n log n) (inserting n elements into the heap).
    • For each of the k operations:
      • Extract the minimum: O(log n)
      • Reinsert the updated value: O(log n).
    • Total: O(n log n + k log n).
    • In most cases, if k is small relative to n, the runtime is dominated by O(n log n).
  2. Space Complexity:
    • The priority queue (min-heap) uses O(n) space to store all the elements.

Posted on

Min Chars to Add for Palindrome

Given a string s, the task is to find the minimum characters to be added at the front to make the string palindrome.

Note: A palindrome string is a sequence of characters that reads the same forward and backward.

Examples:

Input: s = "abc"
Output: 2
Explanation: Add 'b' and 'c' at front of above string to make it palindrome : "cbabc"
Input: s = "aacecaaaa"
Output: 2
Explanation: Add 2 a's at front of above string to make it palindrome : "aaaacecaaaa"

Constraints:
1 <= s.size() <= 106

Solution:

To determine the minimum characters to be added at the front of a string to make it a palindrome, we can solve the problem efficiently using a technique involving the longest prefix of the string that is also a suffix (LPS). This can be computed using the KMP algorithm. Below is the explanation, followed by the implementation.

Key Observation:

To make the string a palindrome by adding only characters to the front:

  • We need to find the longest suffix of the string (starting at the end) that is already a palindrome.
  • Once this suffix is identified, the remaining prefix of the string (which isn’t part of that palindromic suffix) will need to be reversed and added to the front of the string. The count of these characters is the output.

This amounts to finding:

  1. The longest prefix-suffix (LPS) of the string concatenated with its reverse (using a special separator character to avoid false matches).

Let’s break this into steps.

Steps to Find the Minimum Characters:

  1. Concatenate the String and Its Reverse:
    • Create a new string: temp = s + "$" + reverse(s) (we use $ or any separator to distinguish the reversed part from the original string).
  2. Compute Longest Prefix Suffix (LPS):
    • Use the KMP (Knuth-Morris-Pratt) algorithm on temp to compute the LPS array.
    • The LPS array gives us the length of the longest prefix of temp that is also a suffix. This indicates the maximum part of s (from the start) that matches the reverse part.
  3. Calculate Minimum Characters to Add:
    • Subtract the longest prefix-suffix from the length of the original string:
Minimum characters to add = s.length() - LPS[length of temp - 1]

Implementation in C++:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

// Function to compute the LPS array (used in KMP algorithm)
vector<int> computeLPS(const string& str) {
int n = str.length();
vector<int> lps(n, 0); // LPS array
int len = 0; // Length of previous longest prefix suffix
int i = 1;

// Compute LPS array
while (i < n) {
if (str[i] == str[len]) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1]; // Backtrack
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}

// Function to find minimum characters to add at front to make the string palindrome
int minCharsToMakePalindrome(const string& s) {
string reversedStr = s;
reverse(reversedStr.begin(), reversedStr.end());

// Create the concatenated string
string temp = s + "$" + reversedStr;

// Compute LPS array for the concatenated string
vector<int> lps = computeLPS(temp);

// Length of the longest palindromic suffix
int longestPalindromicPrefix = lps.back();

// Minimum characters to add = length of s - longest palindromic prefix
return s.length() - longestPalindromicPrefix;
}

int main() {
string s;
cout << "Enter string: ";
cin >> s;

int result = minCharsToMakePalindrome(s);

cout << "Minimum characters to add: " << result << endl;

return 0;
}

Explanation of Code:

  1. Reverse the String:
    • Create a reversed copy of s (reversedStr).
  2. Concatenate s, $, and reversedStr:
    • This ensures we identify the longest part of s that matches the reversed portion.
    Example:
    If s = “aacecaaa”, then temp = “aacecaaa$aaacecaa”.
  3. Compute LPS Array:
    • Use the KMP algorithm to compute the longest prefix that is also a suffix for temp.
  4. Find the Num of Characters to Add:
    • Subtract the length of the longest palindromic prefix from the total length of s.
Posted on

 Find Minimum in Rotated Sorted Array

https://leetcode.com/problems/find-minimum-in-rotated-sorted-array

Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:

  • [4,5,6,7,0,1,2] if it was rotated 4 times.
  • [0,1,2,4,5,6,7] if it was rotated 7 times.

Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]].

Given the sorted rotated array nums of unique elements, return the minimum element of this array.

You must write an algorithm that runs in O(log n) time.

Example 1:

Input: nums = [3,4,5,1,2]
Output: 1
Explanation: The original array was [1,2,3,4,5] rotated 3 times.

Example 2:

Input: nums = [4,5,6,7,0,1,2]
Output: 0
Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.

Example 3:

Input: nums = [11,13,15,17]
Output: 11
Explanation: The original array was [11,13,15,17] and it was rotated 4 times. 

Key Observations:

  1. A rotated sorted array is a sorted array that has been rotated at some pivot point. For example:
    • Original array: [1, 2, 3, 4, 5]
    • Rotated arrays: [4, 5, 1, 2, 3], [3, 4, 5, 1, 2]
  2. Minimum Element:
    • The minimum element is the only element in the rotated array that is smaller than its predecessor.
    • Alternatively, in the case of no rotation (e.g., [1, 2, 3, 4, 5]), the first element is the smallest.
  3. Binary Search Approach:
    • Since the array is sorted and rotated, we can use binary search to identify the minimum element in O(log n) time.

Steps to Solve:

  1. Binary Search:
    • Set two pointers: low = 0 (start of array) and high = n-1 (end of array).
    • While low < high, compute the middle index: mid = low + (high - low) / 2.
    • Depending on the relationship between arr[mid] and arr[high]:
      • If arr[mid] > arr[high]: The minimum must lie in the right half of the array (set low = mid + 1).
      • Otherwise, the minimum must be in the left half or at mid (set high = mid).
    • When low == high, the minimum element is at index low.
  2. Return the Result:
    • Output the element at arr[low].

Algorithm Complexity:

  • Time Complexity:
    Binary search operates in O(log n) time due to halving the search space in every iteration.
  • Space Complexity:
    The algorithm uses O(1) space as we only manipulate indices and access the array directly.

Implementation in C++:

Here is the efficient implementation:

#include <iostream>
#include <vector>
using namespace std;

int findMinimum(const vector<int>& arr) {
int low = 0, high = arr.size() - 1;

// Binary search to find the minimum element
while (low < high) {
int mid = low + (high - low) / 2;

// If middle element is greater than the last element,
// the minimum must be in the right half
if (arr[mid] > arr[high]) {
low = mid + 1;
}
// Otherwise, the minimum is in the left half (or could be at mid)
else {
high = mid;
}
}

// At this point, low == high and points to the minimum element
return arr[low];
}

int main() {
vector<int> arr = {4, 5, 6, 7, 0, 1, 2}; // Example rotated array
cout << "The minimum element is: " << findMinimum(arr) << endl;

return 0;
}