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:

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: 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 using namespace std; // Function to calculate the last// remaining element from the sequenceint lastRemaining(int n, map &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 Codeint main(){         // Given N    int N = 5;         // Stores the    map dp;         // Function call    cout << lastRemaining(N, dp);         return 0;} // This code is contributed by mohit kumar 29

Java

 // Java program for// the above approachimport java.util.*;class GFG{ // Function to calculate the last// remaining element from the sequencestatic int lastRemaining(int n, HashMap 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 Codepublic static void main(String[] args){     // Given N  int N = 5;   // Stores the  HashMap dp = new HashMap();   // 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 sequencedef 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 NN = 5 # Stores thedp = {} # Function Callprint(lastRemaining(N, dp))

C#

 // C# program for the above approachusing System;using System.Collections.Generic; class GFG{ // Function to calculate the last// remaining element from the sequencestatic int lastRemaining(int n, Dictionary 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 Codepublic static void Main(String[] args){          // Given N    int N = 5;         // Stores the    Dictionary dp = new Dictionary();         // Function call    Console.Write(lastRemaining(N, dp));}} // This code is contributed by Princi Singh

Javascript


Output:
2

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

My Personal Notes arrow_drop_up