Open In App

Maximize median of sequence formed by choosing at least one from adjacent pairs

Given an array Arr[ ] of N integers where 1 ≤ N ≤ 105. The task is to choose any number of elements from the array such that:

Examples:



Input: N = 6,  Arr[ ] = { 2, 1, 2, 1, 1, 10 }
Output: 2
Explanation : Choosing arr[0], arr[2], arr[4] and arr[5] makes the subsequence as { 2, 2, 1, 10 } giving median as 2 which is maximum possible. Also note that the condition that atleast one of the two consecutive elements must be chosen is satisfied.

Input: N = 7, Arr[ ] = { 3, 1, 4, 1, 5, 9, 2 }
Output: 4



 

Approach: The approach is based on binary search technique. 

Below is the implementation of the above approach:




// C++ code for the above approach:
 
#include <bits/stdc++.h>
using namespace std;
 
int dp[100000 + 5][2];
 
// Function to find maximum subsequence sum
// from the array under given condition
// using dynamic programming
int max_subsequence_sum(int arr[], int n,
                        int i, int last)
{
    // If we have taken last element already
    // then last = 1 else last = 0
    if (i >= n) {
        return 0;
    }
 
    // Already calculated and stored in dp
    // ao return directly
    if (dp[i][last] != -1) {
        return dp[i][last];
    }
 
    if (last == 1) {
 
        // Last element is taken already
        // so we can either take
        // the current element or leave it
        int t1 = arr[i]
                 + max_subsequence_sum(arr, n,
                                       i + 1, 1);
 
        int t2 = max_subsequence_sum(arr, n,
                                     i + 1, 0);
 
        return dp[i][last] = max(t1, t2);
    }
    else {
 
        // Last element is not taken
        // Hence we need to take
        // the current element
        int t = arr[i]
                + max_subsequence_sum(arr, n,
                                      i + 1, 1);
 
        return dp[i][last] = t;
    }
}
 
// Helper function to reset
// dp values for each call
int helper_max_sub_sum(int arr[], int n)
{
    memset(dp, -1, sizeof(dp));
 
    int max_sub_sum
        = max_subsequence_sum(arr, n, 0, 1);
 
    return max_sub_sum;
}
 
// Function to check if the given median
// Can be obtained by
// Choosing any subsequence of the array
// Under given constraints
bool is_given_median_possible(int arr[],
                              int n,
                              int median)
{
    int modified[n];
 
    // Creating the modified array as explained
    for (int i{ 0 }; i < n; i++) {
        if (arr[i] >= median) {
            modified[i] = 1;
        }
        else {
            modified[i] = -1;
        }
    }
    int max_sub_sum
        = helper_max_sub_sum(modified, n);
 
    // If max_sub_sum > 0 then current
    // median is possible
    if (max_sub_sum > 0) {
        return true;
    }
    return false;
}
 
// Function to binary search
// Over all possible values of median
// To find the max possible median
int binary_search_for_median(int arr[],
                             int n)
{
    int ans = 1;
    int low = *min_element(arr, arr + n);
    int high = *max_element(arr, arr + n);
 
    while (low <= high) {
        int mid = low + (high - low) / 2;
 
        if (is_given_median_possible(arr,
                                     n, mid)) {
            ans = mid;
            low = mid + 1;
        }
        else {
            high = mid - 1;
        }
    }
    return ans;
}
 
// Driver code
int main()
{
    int N = 7;
    int Arr[] = { 3, 1, 4, 1, 5, 9, 2 };
 
    // Storing the function in ans variable
    int ans = binary_search_for_median(Arr, N);
    cout << ans << endl;
    return 0;
}




// Java code for the above approach
import java.util.*;
class GFG
{
 
  static int dp[][] = new int[100000 + 5][2];
 
  // Function to find maximum subsequence sum
  // from the array under given condition
  // using dynamic programming
  static int max_subsequence_sum(int arr[], int n,
                                 int i, int last)
  {
    // If we have taken last element already
    // then last = 1 else last = 0
    if (i >= n) {
      return 0;
    }
 
    // Already calculated and stored in dp
    // ao return directly
    if (dp[i][last] != -1) {
      return dp[i][last];
    }
 
    if (last == 1) {
 
      // Last element is taken already
      // so we can either take
      // the current element or leave it
      int t1 = arr[i]
        + max_subsequence_sum(arr, n,
                              i + 1, 1);
 
      int t2 = max_subsequence_sum(arr, n,
                                   i + 1, 0);
 
      return dp[i][last] = Math.max(t1, t2);
    }
    else {
 
      // Last element is not taken
      // Hence we need to take
      // the current element
      int t = arr[i]
        + max_subsequence_sum(arr, n,
                              i + 1, 1);
 
      return dp[i][last] = t;
    }
  }
 
  // Helper function to reset
  // dp values for each call
  static int helper_max_sub_sum(int arr[], int n)
  {
    for(int i=0;i<dp.length;i++){
      for(int j=0;j<dp[i].length;j++){
        dp[i][j]= -1;
      }
    }
 
    int max_sub_sum
      = max_subsequence_sum(arr, n, 0, 1);
 
    return max_sub_sum;
  }
 
  // Function to check if the given median
  // Can be obtained by
  // Choosing any subsequence of the array
  // Under given constraints
  static boolean is_given_median_possible(int arr[],
                                          int n,
                                          int median)
  {
    int modified[] = new int[n];
 
    // Creating the modified array as explained
    for (int i =0; i < n; i++) {
      if (arr[i] >= median) {
        modified[i] = 1;
      }
      else {
        modified[i] = -1;
      }
    }
    int max_sub_sum
      = helper_max_sub_sum(modified, n);
 
    // If max_sub_sum > 0 then current
    // median is possible
    if (max_sub_sum > 0) {
      return true;
    }
    return false;
  }
 
  // Function to binary search
  // Over all possible values of median
  // To find the max possible median
  static int binary_search_for_median(int arr[],
                                      int n)
  {
    int ans = 1;
 
    int low = 99999999;
    int high = -9999999;
 
 
 
 
    for(int i=0;i<arr.length;i++)
    {
      low = Math.min(low, arr[i]);
      high = Math.max(high, arr[i]);
    }
 
    while (low <= high) {
      int mid = low + (high - low) / 2;
 
      if (is_given_median_possible(arr,
                                   n, mid)==true) {
        ans = mid;
        low = mid + 1;
      }
      else {
        high = mid - 1;
      }
    }
    return ans;
  }
 
  // Driver code
  public static void main (String[] args) {
    int N = 7;
    int Arr[] = { 3, 1, 4, 1, 5, 9, 2 };
 
    // Storing the function in ans variable
    int ans = binary_search_for_median(Arr, N);
    System.out.println( ans);
  }
}
 
// This code is contributed by Potta Lokesh




# Python code for the above approach
 
# Function to find maximum subsequence sum
# from the array under given condition
# using dynamic programming
def max_subsequence_sum(arr, n, i, last):
    if i >= n:
        return 0
    if dp[i][last] != -1:
        return dp[i][last]
    if last == 1:
        t1 = arr[i] + max_subsequence_sum(arr, n, i+1, 1)
        t2 = max_subsequence_sum(arr, n, i+1, 0)
        dp[i][last] = max(t1, t2)
        return dp[i][last]
    else:
        t = arr[i] + max_subsequence_sum(arr, n, i+1, 1)
        dp[i][last] = t
        return dp[i][last]
 
# Helper function to reset
# dp values for each call
def helper_max_sub_sum(arr, n):
    global dp
    dp = [[-1 for i in range(2)] for i in range(100000 + 5)]
    max_sub_sum = max_subsequence_sum(arr, n, 0, 1)
    return max_sub_sum
 
# Function to check if the given median
# Can be obtained by
# Choosing any subsequence of the array
# Under given constraints
def is_given_median_possible(arr, n, median):
    modified = [[-1, 1][arr[i] >= median] for i in range(n)]
    max_sub_sum = helper_max_sub_sum(modified, n)
    return max_sub_sum > 0
 
# Function to binary search
# Over all possible values of median
# To find the max possible median
def binary_search_for_median(arr, n):
    ans = 1
    low = min(arr)
    high = max(arr)
    while (low <= high):
        mid = int(low + (high - low)/2)
        if (is_given_median_possible(arr, n, mid)):
            ans = mid
            low = mid + 1
        else:
            high = mid - 1
 
    return ans
 
# Driver Code
N = 7
Arr = [3, 1, 4, 1, 5, 9, 2]
ans = binary_search_for_median(Arr, N)
print(ans)
 
# This code is contributed by phalasi.




// C# code for the above approach
using System;
 
public class GFG{
 
  static int [,] dp = new int[100000 + 5, 2];
 
  // Function to find maximum subsequence sum
  // from the array under given condition
  // using dynamic programming
  static int max_subsequence_sum(int[] arr, int n,
                                 int i, int last)
  {
    // If we have taken last element already
    // then last = 1 else last = 0
    if (i >= n) {
      return 0;
    }
 
    // Already calculated and stored in dp
    // ao return directly
    if (dp[i, last] != -1) {
      return dp[i, last];
    }
 
    if (last == 1) {
 
      // Last element is taken already
      // so we can either take
      // the current element or leave it
      int t1 = arr[i]
        + max_subsequence_sum(arr, n,
                              i + 1, 1);
 
      int t2 = max_subsequence_sum(arr, n,
                                   i + 1, 0);
 
      return dp[i, last] = Math.Max(t1, t2);
    }
    else {
 
      // Last element is not taken
      // Hence we need to take
      // the current element
      int t = arr[i]
        + max_subsequence_sum(arr, n,
                              i + 1, 1);
 
      return dp[i, last] = t;
    }
  }
 
  // Helper function to reset
  // dp values for each call
  static int helper_max_sub_sum(int[] arr, int n)
  {
    for(int i=0;i<dp.GetLength(0);i++){
      for(int j=0;j < dp.GetLength(1);j++){
        dp[i, j]= -1;
      }
    }
 
    int max_sub_sum
      = max_subsequence_sum(arr, n, 0, 1);
 
    return max_sub_sum;
  }
 
  // Function to check if the given median
  // Can be obtained by
  // Choosing any subsequence of the array
  // Under given constraints
  static bool is_given_median_possible(int[] arr,
                                       int n,
                                       int median)
  {
    int[] modified = new int[n];
 
    // Creating the modified array as explained
    for (int i =0; i < n; i++) {
      if (arr[i] >= median) {
        modified[i] = 1;
      }
      else {
        modified[i] = -1;
      }
    }
    int max_sub_sum
      = helper_max_sub_sum(modified, n);
 
    // If max_sub_sum > 0 then current
    // median is possible
    if (max_sub_sum > 0) {
      return true;
    }
    return false;
  }
 
  // Function to binary search
  // Over all possible values of median
  // To find the max possible median
  static int binary_search_for_median(int[] arr,
                                      int n)
  {
    int ans = 1;
 
    int low = 99999999;
    int high = -9999999;
 
 
 
 
    for(int i=0;i<arr.Length;i++)
    {
      low = Math.Min(low, arr[i]);
      high = Math.Max(high, arr[i]);
    }
 
    while (low <= high) {
      int mid = low + (high - low) / 2;
 
      if (is_given_median_possible(arr,
                                   n, mid)==true) {
        ans = mid;
        low = mid + 1;
      }
      else {
        high = mid - 1;
      }
    }
    return ans;
  }
 
  // Driver code
  static public void Main (){
 
    int N = 7;
    int[] Arr = { 3, 1, 4, 1, 5, 9, 2 };
 
    // Storing the function in ans variable
    int ans = binary_search_for_median(Arr, N);
    Console.Write( ans);
  }
}
 
// This code is contributed by hrithikgarg0388.




<script>
    // JavaScript code for the above approach:
    let dp = new Array(100000 + 5).fill(0).map(() => new Array(2).fill(0));
 
    // Function to find maximum subsequence sum
    // from the array under given condition
    // using dynamic programming
    const max_subsequence_sum = (arr, n, i, last) => {
     
        // If we have taken last element already
        // then last = 1 else last = 0
        if (i >= n) {
            return 0;
        }
 
        // Already calculated and stored in dp
        // ao return directly
        if (dp[i][last] != -1) {
            return dp[i][last];
        }
 
        if (last == 1) {
 
            // Last element is taken already
            // so we can either take
            // the current element or leave it
            let t1 = arr[i]
                + max_subsequence_sum(arr, n,
                    i + 1, 1);
 
            let t2 = max_subsequence_sum(arr, n,
                i + 1, 0);
 
            return dp[i][last] = Math.max(t1, t2);
        }
        else {
 
            // Last element is not taken
            // Hence we need to take
            // the current element
            let t = arr[i]
                + max_subsequence_sum(arr, n,
                    i + 1, 1);
 
            return dp[i][last] = t;
        }
    }
 
    // Helper function to reset
    // dp values for each call
    const helper_max_sub_sum = (arr, n) => {
        for (let i = 0; i < dp.length; ++i) {
            for (let j = 0; j < dp[0].length; ++j) dp[i][j] = -1;
        }
        let max_sub_sum
            = max_subsequence_sum(arr, n, 0, 1);
 
        return max_sub_sum;
    }
 
    // Function to check if the given median
    // Can be obtained by
    // Choosing any subsequence of the array
    // Under given constraints
    const is_given_median_possible = (arr, n, median) => {
        let modified = new Array(n).fill(0);
 
        // Creating the modified array as explained
        for (let i = 0; i < n; i++) {
            if (arr[i] >= median) {
                modified[i] = 1;
            }
            else {
                modified[i] = -1;
            }
        }
        let max_sub_sum
            = helper_max_sub_sum(modified, n);
 
        // If max_sub_sum > 0 then current
        // median is possible
        if (max_sub_sum > 0) {
            return true;
        }
        return false;
    }
 
    // Function to binary search
    // Over all possible values of median
    // To find the max possible median
    const binary_search_for_median = (arr, n) => {
        let ans = 1;
        let low = Math.min(...arr);
        let high = Math.max(...arr);
 
        while (low <= high) {
            let mid = low + parseInt((high - low) / 2);
 
            if (is_given_median_possible(arr,
                n, mid)) {
                ans = mid;
                low = mid + 1;
            }
            else {
                high = mid - 1;
            }
        }
        return ans;
    }
 
    // Driver code
 
    let N = 7;
    let Arr = [3, 1, 4, 1, 5, 9, 2];
 
    // Storing the function in ans variable
    let ans = binary_search_for_median(Arr, N);
    document.write(ans);
 
// This code is contributed by rakeshsahni
 
</script>

 
 

Output
4

 

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

 


Article Tags :