Value of k-th index of a series formed by append and insert MEX in middle


In this article, we will learn about Mex and will also generate the C++ code that returns the kth index of the series so formed by using append and MEX (>0) operations on the given sequence.

The roadmap of the operations to be performed is given below −

Start with a sequence containing only the number 1 i.e, [1].

Now, we need to perform (n-1) steps −

  • In each step, we append the current series by itself. For example, if the existing series is [1, 2, 3], after appending, it becomes [1, 2, 3, 1, 2, 3].

  • Now, find the minimum excluded value that is, (MEX) of the series. This is the smallest positive integer that doesn't appear in the series. Hence the MEX for this sequence is − 4.

  • Insert the MEX value into the middle of the sequence. This means placing it between the two halves of the sequence. For example, if the sequence is [1, 2, 3, 1, 2, 3], and the MEX is 4, the resulting sequence after inserting the MEX becomes [1, 2, 3, 4, 1, 2, 3].

  • Repeat these steps for each subsequent iteration until you complete (n-1) steps. After performing all the steps, we have the resulting sequence.

  • Our goal is to determine the integer present at the k-th index of the existing series. We can Simply access the k-th index of the sequence to find the desired output.

Approach 1: Brute Force Approach

The first and brute force approach for this will be- Just follow all the steps given in the problem statement and at last return the desired index.

Example

The implementation of this brute force approach with C++ is given below.

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

int find_mex(vector<int>& seq) {
   int mex = 1;
   while (find(seq.begin(), seq.end(), mex) != seq.end()) {
      mex++;
   }
   return mex;
}
int find_value(int number, int index) {
   vector<int> seq = {1};
   int iterator = 1;
   for (iterator = 1; iterator < number ; iterator++){
      int mex = find_mex(seq);
      seq.insert(seq.end(), seq.begin(), seq.end());
      seq.insert(seq.begin() + seq.size() / 2, mex);
   }
   return seq[index - 1];
}
int main(){
   int number = 4;
   int index = 8;
   int result = find_value(number , index);
   cout << "The value at index " << index <<  " after "  << number << " steps is: " << result << endl;
   return 0;
}

Output

The value at index 8 after 4 steps is: 4
  • Time Complexity − The time complexity of the code implemented above is quadratic, denoted as O(n^2), as a result of the nested execution of the find_value and find_mex functions

  • Space Complexity − The auxiliary space required for the approach implemented above is also O(n^2) as the sequence grows exponentially in size as we append it to itself in each iteration.

Approach 2: The binary search approach

Another approach which can be used is binary search approach. It is observed that the element at the middle of the resulting series is always equal to n. The length of the series is 2n - 1, where the lengths of the series follow the pattern (1, 3, 7, 15, ..., 2n - 1).

We can apply binary search to solve this problem efficiently. We start our search from nth step and compare the index at the middle with the value of k. If the middle index is equal to k, we return n because the middle element at step n is n itself. If the middle index is not equal to k, we will update our search range based on the value of k. If k is greater than the index at middle, we continue the search in the second half of the range; otherwise, we search in the first half.

We will repeat this process until we find the index k. In each iteration, we decrement the value of n by 1 and then we will update our search accordingly.

Example

The implementation of this approach with C++ is given below.

#include <bits/stdc++.h>
using namespace std;
int getIndex(int number , int index){
   int middle_element = number ;
   int l = 1;
   int r = pow(2, number) - 1;
   while (1) {
      int middle = (l + r) / 2;
      if (index == middle) {
         return middle_element;
         break;
      }
      middle_element--;
      if (index < middle)
         r = middle - 1;
      else
         l = middle + 1;
   }
}
int main(){
   int number = 4;
   int index = 8;
   int result = getIndex(number , index);
   cout << "The value at index " << index <<  " after "  << number << " steps is: " << result << endl;
   return 0;
}

Output

The value at index 8 after 4 steps is: 4
  • Time complexity − As we are using binary search in this approach, the time complexity will be reduced to O(log(n))

  • Space Complexity − The additional space required by this approach remains constant, regardless of the input size, with a complexity of O(1).

Conclusion

We discussed two different approaches to solve the given problem, the first approach used was a basic brute force approach in which, the time complexity was of order O(n^2) due to which, the first approach was not efficient. Later on, we implemented the binary search approach which reduced the time complexity of the solution to O(log(n)) which is very efficient comparatively. We also reduced the space complexity to constant space.

Updated on: 05-Oct-2023

33 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements