Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Find the last remaining element after repeated removal of odd and even indexed elements alternately

  • Last Updated : 31 May, 2021

Given a positive integer N, the task is to print the last remaining element from a sequence [1, N] after repeatedly performing the following operations in the given order alternately:

  1. Remove all the odd-indexed elements from the sequence.
  2. Remove all the even-indexed elements from the sequence.

Examples:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: N = 9
Output: 6
Explanation: 
Sequence = {1, 2, 3, 4, 5, 6, 7, 8, 9}
Step 1: Removing odd-indexed elements modifies sequence to {2, 4, 6, 8}
Step 2: Removing even-indexed elements modifies sequence to {2, 6}
Step 3: Removing odd-indexed elements modifies sequence to {6}
Therefore, the last remaining element is 6.



Input: N = 5
Output: 2
Explanation: 
Sequence = {1, 2, 3, 4, 5}
Step 1: Removing odd-indexed elements modifies sequence to {2, 4}
Step 2: Removing even-indexed elements modifies sequence to {2}
Therefore, the last remaining element is 2.

Naive Approach: The simplest approach is to store all the elements from 1 to N sequentially in an array. For every operation, remove elements from the array and shift the remaining elements towards the left. After reducing the array to a single element, print that remaining element as the required answer. 

Time Complexity: O(N2*log N)
Auxiliary Space: O(N)

Efficient Approach: The above approach can be optimized using Dynamic Programming
The recurrence relation is as follows:

dp[i] = 2*(1 + \frac{i}{2} - dp(\frac{i}{2}))
 

where, i is in the range [1, N]
dp[i] stores the answer when the array elements are from 1 to i.

Follow the steps below to solve the problem:

  1. Initialize an array dp[] where dp[i] stores the remaining element or the sequence [1, i].
  2. For the base condition of i = 1, print 1 as the required answer.
  3. Calculate the value of dp[N] using the aforementioned recurrence relation and use the already computed subproblems to avoid recomputation of overlapping subproblems.
  4. After completing the above steps, print the value of dp[N] as the result.

Below is the implementation of the above approach:

C++14




// C++14 program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate the last
// remaining element from the sequence
int lastRemaining(int n, map<int, int> &dp)
{
     
    // If dp[n] is already calculated
    if (dp.find(n) != dp.end())
        return dp[n];
 
    // Base Case:
    if (n == 1)
        return 1;
     
    // Recursive call
    else
        dp[n] = 2 * (1 + n / 2 -
           lastRemaining(n / 2, dp));
 
    // Return the value of dp[n]
    return dp[n];
}
 
// Driver Code
int main()
{
     
    // Given N
    int N = 5;
     
    // Stores the
    map<int, int> dp;
     
    // Function call
    cout << lastRemaining(N, dp);
     
    return 0;
}
 
// This code is contributed by mohit kumar 29

Java




// Java program for
// the above approach
import java.util.*;
class GFG{
 
// Function to calculate the last
// remaining element from the sequence
static int lastRemaining(int n, HashMap<Integer,
                                        Integer> dp)
{
  // If dp[n] is already calculated
  if (dp.containsKey(n))
    return dp.get(n);
 
  // Base Case:
  if (n == 1)
    return 1;
 
  // Recursive call
  else
    dp.put(n, 2 * (1 + n / 2 -
           lastRemaining(n / 2, dp)));
 
  // Return the value of dp[n]
  return dp.get(n);
}
 
// Driver Code
public static void main(String[] args)
{   
  // Given N
  int N = 5;
 
  // Stores the
  HashMap<Integer,
          Integer> dp = new HashMap<Integer,
                                    Integer>();
 
  // Function call
  System.out.print(lastRemaining(N, dp));
}
}
 
// This code is contributed by Princi Singh

Python3




# Python program for the above approach
 
# Function to calculate the last
# remaining element from the sequence
def lastRemaining(n, dp):
 
  # If dp[n] is already calculated
    if n in dp:
        return dp[n]
 
    # Base Case:
    if n == 1:
        return 1
 
    # Recursive Call
    else:
        dp[n] = 2*(1 + n//2
        - lastRemaining(n//2, dp))
 
    # Return the value of dp[n]
    return dp[n]
 
 
# Driver Code
 
# Given N
N = 5
 
# Stores the
dp = {}
 
# Function Call
print(lastRemaining(N, dp))

C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to calculate the last
// remaining element from the sequence
static int lastRemaining(int n, Dictionary<int,
                                           int> dp)
{
     
    // If dp[n] is already calculated
    if (dp.ContainsKey(n))
        return dp[n];
     
    // Base Case:
    if (n == 1)
        return 1;
     
    // Recursive call
    else
        dp.Add(n, 2 * (1 + n / 2 -
             lastRemaining(n / 2, dp)));
     
    // Return the value of dp[n]
    return dp[n];
}
 
// Driver Code
public static void Main(String[] args)
     
    // Given N
    int N = 5;
     
    // Stores the
    Dictionary<int,
               int> dp = new Dictionary<int,
                                        int>();
     
    // Function call
    Console.Write(lastRemaining(N, dp));
}
}
 
// This code is contributed by Princi Singh

Javascript




<script>
      // JavaScript program for the above approach
      // Function to calculate the last
      // remaining element from the sequence
      function lastRemaining(n, dp) {
        // If dp[n] is already calculated
        if (dp.hasOwnProperty(n))
            return dp[n];
 
        // Base Case:
        if (n === 1)
            return 1;
        // Recursive call
        else
          dp[n] =
            2 * (1 + parseInt(n / 2) -
            lastRemaining(parseInt(n / 2), dp));
 
        // Return the value of dp[n]
        return dp[n];
      }
 
      // Driver Code
      // Given N
      var N = 5;
 
      // Stores the
      var dp = {};
 
      // Function call
      document.write(lastRemaining(N, dp));
</script>
Output: 
2

 

Time Complexity: O(N)
Auxiliary Space: O(N)




My Personal Notes arrow_drop_up
Recommended Articles
Page :