Find Subarray whose end points don’t have maximum or minimum
Last Updated :
23 Apr, 2023
Given an array nums[] of length N which contains integers, the task is to find a subarray such that the first and the last element of that subarray is neither the maximum nor minimum element present in that subarray and print the starting and ending index if there is such a subarray otherwise print -1.
Examples:
Input: N = 7, nums = [1, 3, 2, 4, 6, 5, 7]
Output: start = 1, end = 5
Explanation: Subarray starting from the 1st index and ending at 5th index follows the rule that is:
minimum in the subarray is 2, maximum in the subarray is 5 so,
nums[1] = 3 and nums[5] = 5 which is neither the minimum nor maximum of that subarray.
Input: N = 6, nums = [2, 3, 6, 5, 4, 1]
Output: -1
Approach: To solve the problem follow the below idea:
We will use two Priority Queues, one of increasing type and the other of decreasing type, and at the same time, we will point two pointers at the start and at the end of the array respectively. Now, those two priority queue contains the maximum and minimum element of the current subarray formed by those two pointers and if the peek() element of those priority queues is not equal to either of the pointed indexed array then we will print the subarray.
For a clear understanding, see the below explanation for the above test case:
Suppose for the above example where N = 7 and nums[] = [1, 3, 2, 4, 6, 5, 7], we will have two priority queue one which is increasing and the other which is decreasing and they will contain:
- increasing: [1, 3, 2, 4, 6, 5, 7] and decreasing: [7, 4, 6, 1, 3, 2, 5] and, our two pointer is at i = 0, and j = 6.
- As nums[i] == increasing.peek() = 1, so we will increment i, also remove a top element from the
- increasing priority queue, after that our two pointers and two priority queue will be:
- increasing: [2, 3, 5, 4, 6, 7], decreasing = [7, 4, 6, 1, 3, 2, 5], i = 1, and j = 6.
- As nums[j] == decreasing.peek() = 7, so we will decrement j and remove the top element from the
- decreasing priority queue, after that our pointers and priority queues will be:
- increasing: [2, 3, 5, 4, 6, 7], decreasing: [6, 4, 5, 1, 3, 2], i = 1 and j = 5.
- Now nums[i], as well as nums[j], is not equal to any of the peek() elements from the priority queues
- Which means this subarray satisfies our condition, so we will print it.
- If in any case i crosses j without satisfying the condition then we will print -1.
Steps to follow to solve the problem:
- Enter all elements in two priority queues, one which is decreasing and the other which is increasing.
- Now we will use two pointer approach, one pointer will start from the 0th index and the other from (N -1)th index.
- If the first indexed element is equal to either of the peek() elements of the maximum priority queue or minimum priority queue we will increment it or if, the second indexed element is equal to either of the peek() element of the maximum priority queue or minimum priority queue we will decrement it.
- If none of the indexed element is equal to the peek() element of the maximum and minimum priority queue, we will print those indices and mark a boolean flag to true which signify that there exist such requires subarray.
- If the flag is false or null, then we will print -1.
- To understand the concept, use the below explanation.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#include <iostream>
#include <queue>
using namespace std;
int findSubArray( int nums[], int N)
{
priority_queue< int > decreasing;
priority_queue< int , vector< int >, greater< int > >
increasing;
for ( int i=0 ; i<N ; i++) {
decreasing.push(nums[i]);
increasing.push(nums[i]);
}
int i = 0;
int j = N - 1;
bool flag = true ;
while (i <= j && flag) {
if (nums[i] == decreasing.top()) {
i++;
decreasing.pop();
}
else if (nums[i] == increasing.top()) {
i++;
increasing.pop();
}
else if (nums[j] == decreasing.top()) {
j--;
decreasing.pop();
}
else if (nums[j] == increasing.top()) {
j--;
increasing.pop();
}
else
flag = false ;
}
if (flag)
cout << -1 << endl;
else
cout << "start = " << i << ", "
<< "end = " << j << endl;
}
int main()
{
int N = 7;
int nums[] = { 1, 3, 2, 4, 6, 5, 7 };
findSubArray(nums, N);
}
|
Java
import java.util.*;
class GFG {
public static void main(String[] args)
{
int N = 7 ;
int [] nums = { 1 , 3 , 2 , 4 , 6 , 5 , 7 };
findSubArray(nums, N);
}
public static void findSubArray( int [] nums, int N)
{
PriorityQueue<Integer> decreasing
= new PriorityQueue<>(
Collections.reverseOrder());
PriorityQueue<Integer> increasing
= new PriorityQueue<>();
for ( int v : nums) {
decreasing.add(v);
increasing.add(v);
}
int i = 0 ;
int j = N - 1 ;
boolean flag = true ;
while (i <= j && flag) {
if (nums[i] == decreasing.peek()) {
i++;
decreasing.remove();
}
else if (nums[i] == increasing.peek()) {
i++;
increasing.remove();
}
else if (nums[j] == decreasing.peek()) {
j--;
decreasing.remove();
}
else if (nums[j] == increasing.peek()) {
j--;
increasing.remove();
}
else
flag = false ;
}
if (flag)
System.out.println(- 1 );
else
System.out.println( "start = " + i + ", "
+ "end = " + j);
}
}
|
Python3
import heapq
def findSubArray(nums, N):
decreasing = []
increasing = []
for i in range (N):
heapq.heappush(decreasing, - nums[i])
heapq.heappush(increasing, nums[i])
i = 0
j = N - 1
flag = True
while i < = j and flag:
if nums[i] = = - decreasing[ 0 ]:
i + = 1
heapq.heappop(decreasing)
elif nums[i] = = increasing[ 0 ]:
i + = 1
heapq.heappop(increasing)
elif nums[j] = = - decreasing[ 0 ]:
j - = 1
heapq.heappop(decreasing)
elif nums[j] = = increasing[ 0 ]:
j - = 1
heapq.heappop(increasing)
else :
flag = False
if flag:
print ( - 1 )
else :
print ( "start =" , i, ", end =" , j)
N = 7
nums = [ 1 , 3 , 2 , 4 , 6 , 5 , 7 ]
findSubArray(nums, N)
|
C#
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
int N = 7;
int [] nums = { 1, 3, 2, 4, 6, 5, 7 };
FindSubArray(nums, N);
}
public static void FindSubArray( int [] nums, int N)
{
var decreasing = new List< int >();
var increasing = new List< int >();
int i;
for (i = 0; i < N; i++)
{
decreasing.Add(-nums[i]);
increasing.Add(nums[i]);
}
decreasing.Sort();
increasing.Sort();
i = 0;
int j = N - 1;
bool flag = true ;
while (i <= j && flag)
{
if (nums[i] == -decreasing[0])
{
i++;
decreasing.RemoveAt(0);
}
else if (nums[i] == increasing[0])
{
i++;
increasing.RemoveAt(0);
}
else if (nums[j] == -decreasing[0])
{
j--;
decreasing.RemoveAt(0);
}
else if (nums[j] == increasing[0])
{
j--;
increasing.RemoveAt(0);
}
else
{
flag = false ;
}
}
if (flag)
{
Console.WriteLine(-1);
}
else
{
Console.WriteLine( "start = " + i + ", end = " + j);
}
}
}
|
Javascript
function findSubArray(nums, N) {
let decreasing = [];
let increasing = [];
for (let i = 0; i < N; i++) {
decreasing.push(-nums[i]);
increasing.push(nums[i]);
}
decreasing.sort( function (a, b){ return b - a});
increasing.sort( function (a, b){ return a - b});
let i = 0;
let j = N - 1;
let flag = true ;
while (i <= j && flag) {
if (nums[i] == -decreasing[0]) {
i += 1;
decreasing.shift();
}
else if (nums[i] == increasing[0]) {
i += 1;
increasing.shift();
}
else if (nums[j] == -decreasing[0]) {
j -= 1;
decreasing.shift();
}
else if (nums[j] == increasing[increasing.length - 1]) {
j -= 1;
increasing.pop();
}
else {
flag = false ;
}
}
if (flag) {
console.log(-1);
}
else {
console.log(`start = ${i}, end = ${j}`);
}
}
let N = 7;
let nums = [1, 3, 2, 4, 6, 5, 7];
findSubArray(nums, N);
|
Output
start = 1, end = 5
Time Complexity: O(N * log(N)), log(N) for the priority queue.
Auxiliary Space: O(N) is used by the priority queue.
Share your thoughts in the comments
Please Login to comment...