Remove minimum elements from either side such that 2*min becomes more than max | Set 2

Given an unsorted array, trim the array such that twice of minimum is greater than the maximum in the trimmed array. Elements should be removed from either end of the array. The number of removals should be minimum.

Examples:

Input: arr[] = {4, 5, 100, 9, 10, 11, 12, 15, 200} Output: 4 We need to remove 4 elements (4, 5, 100, 200) so that 2*min becomes more than max. Input: arr[] = {4, 7, 5, 6} Output: 0 We don’t need to remove any element as 4*2 > 7 Input: arr[] = {20, 7, 5, 6} Output: 1

Approach:

We have discussed various approaches to solve this problem in O(n

3

), O(n

2

* logn), and O(n

2

) time in

previous article

. In this articles, we are going to discuss a O(n * logn) time solution using

Sliding Window

and

Segment Tree

concepts.

1. Construct Segment Tree for RangeMinimumQuery and RangeMaximumQuery for the given input array.
2. Take two pointers start and end, and initialize both to 0.
3. While end is less than the length of the input array, do the following:
• Find min and max in the current window using Segment Trees constructed in step 1.
• Check if 2 * min â‰¤ max, if so then increment start pointer else update max valid length so far, if required
• Increment end
4. length(arr[]) – maxValidLength is the required answer.

Below is the implementation of the above approach:

C++

 `#include ``#include ``#include ``#include ``using` `namespace` `std;` `class` `GFG {``public``:``    ``int` `removeMinElements(vector<``int``>& a) {``        ``int` `n = a.size();` `        ``RangeMinimumQuery rMimQ;``        ``vector<``int``> minTree = rMimQ.createSegmentTree(a);` `        ``RangeMaximumQuery rMaxQ;``        ``vector<``int``> maxTree = rMaxQ.createSegmentTree(a);` `        ``int` `start = 0;``        ``int` `end = 0;` `        ``// To store min and max in the current window``        ``int` `min_val = 0;``        ``int` `max_val = 0;``        ``int` `maxValidLen = 0;` `        ``while` `(end < n) {``            ``min_val = rMimQ.rangeMinimumQuery(minTree, start, end, n);``            ``max_val = rMaxQ.rangeMaximumQuery(maxTree, start, end, n);``            ``if` `(2 * min_val <= max_val)``                ``start++;``            ``else``                ``maxValidLen = max(maxValidLen, end - start + 1);``            ``end++;``        ``}``        ``return` `n - maxValidLen;``    ``}` `    ``class` `RangeMinimumQuery {``    ``public``:``        ``vector<``int``> createSegmentTree(vector<``int``>& input) {``            ``int` `n = input.size();``            ``int` `segTreeSize = 2 * get_next_power_of_two(n) - 1;``            ``vector<``int``> segmentTree(segTreeSize, 0);` `            ``createSegmentTreeUtil(segmentTree, input, 0, n - 1, 0);``            ``return` `segmentTree;``        ``}` `        ``void` `createSegmentTreeUtil(vector<``int``>& segmentTree, vector<``int``>& input, ``int` `low, ``int` `high, ``int` `pos) {``            ``if` `(low == high) {``                ``// It's a leaf node``                ``segmentTree[pos] = input[low];``                ``return``;``            ``}` `            ``// Construct left and right subtrees and then``            ``// update value for the current node``            ``int` `mid = (low + high) / 2;``            ``createSegmentTreeUtil(segmentTree, input, low, mid, (2 * pos + 1));``            ``createSegmentTreeUtil(segmentTree, input, mid + 1, high, (2 * pos + 2));``            ``segmentTree[pos] = min(segmentTree[2 * pos + 1], segmentTree[2 * pos + 2]);``        ``}` `        ``int` `rangeMinimumQuery(vector<``int``>& segmentTree, ``int` `from, ``int` `to, ``int` `inputSize) {``            ``return` `rangeMinimumQueryUtil(segmentTree, 0, inputSize - 1, from, to, 0);``        ``}` `        ``int` `rangeMinimumQueryUtil(vector<``int``>& segmentTree, ``int` `low, ``int` `high, ``int` `from, ``int` `to, ``int` `pos) {``            ``// Total overlap``            ``if` `(from <= low && to >= high) {``                ``return` `segmentTree[pos];``            ``}` `            ``// No overlap``            ``if` `(from > high || to < low) {``                ``return` `INT_MAX;``            ``}` `            ``// Partial overlap``            ``int` `mid = (low + high) / 2;``            ``int` `left = rangeMinimumQueryUtil(segmentTree, low, mid, from, to, (2 * pos + 1));``            ``int` `right = rangeMinimumQueryUtil(segmentTree, mid + 1, high, from, to, (2 * pos + 2));``            ``return` `min(left, right);``        ``}` `    ``private``:``        ``int` `get_next_power_of_two(``int` `n) {``            ``int` `logPart = ``ceil``(log2(n));``            ``return` `pow``(2, logPart);``        ``}``    ``};` `    ``class` `RangeMaximumQuery {``    ``public``:``        ``vector<``int``> createSegmentTree(vector<``int``>& input) {``            ``int` `n = input.size();``            ``int` `segTreeSize = 2 * get_next_power_of_two(n) - 1;``            ``vector<``int``> segmentTree(segTreeSize, 0);` `            ``createSegmentTreeUtil(segmentTree, input, 0, n - 1, 0);``            ``return` `segmentTree;``        ``}` `        ``void` `createSegmentTreeUtil(vector<``int``>& segmentTree, vector<``int``>& input, ``int` `low, ``int` `high, ``int` `pos) {``            ``if` `(low == high) {``                ``// It's a leaf node``                ``segmentTree[pos] = input[low];``                ``return``;``            ``}` `            ``// Construct left and right subtrees and then``            ``// update value for the current node``            ``int` `mid = (low + high) / 2;``            ``createSegmentTreeUtil(segmentTree, input, low, mid, (2 * pos + 1));``            ``createSegmentTreeUtil(segmentTree, input, mid + 1, high, (2 * pos + 2));``            ``segmentTree[pos] = max(segmentTree[2 * pos + 1], segmentTree[2 * pos + 2]);``        ``}` `        ``int` `rangeMaximumQuery(vector<``int``>& segmentTree, ``int` `from, ``int` `to, ``int` `inputSize) {``            ``return` `rangeMaximumQueryUtil(segmentTree, 0, inputSize - 1, from, to, 0);``        ``}` `        ``int` `rangeMaximumQueryUtil(vector<``int``>& segmentTree, ``int` `low, ``int` `high, ``int` `from, ``int` `to, ``int` `pos) {``            ``// Total overlap``            ``if` `(from <= low && to >= high) {``                ``return` `segmentTree[pos];``            ``}` `            ``// No overlap``            ``if` `(from > high || to < low) {``                ``return` `INT_MIN;``            ``}` `            ``// Partial overlap``            ``int` `mid = (low + high) / 2;``            ``int` `left = rangeMaximumQueryUtil(segmentTree, low, mid, from, to, (2 * pos + 1));``            ``int` `right = rangeMaximumQueryUtil(segmentTree, mid + 1, high, from, to, (2 * pos + 2));``            ``return` `max(left, right);``        ``}` `    ``private``:``        ``int` `get_next_power_of_two(``int` `n) {``            ``int` `logPart = ``ceil``(log2(n));``            ``return` `pow``(2, logPart);``        ``}``    ``};``};` `int` `main() {``    ``vector<``int``> a = {4, 5, 100, 9, 10, 11, 12, 15, 200};``    ``GFG gfg;``    ``cout << gfg.removeMinElements(a) << endl;``    ``return` `0;``}`

Java

 `// Java implementation of the approach``public` `class` `GFG {` `    ``// Function to return the minimum removals``    ``// required so that the array satisfy``    ``// the given condition``    ``public` `int` `removeMinElements(``int``[] a)``    ``{``        ``int` `n = a.length;` `        ``RangeMinimumQuery rMimQ = ``new` `RangeMinimumQuery();``        ``int``[] minTree = rMimQ.createSegmentTree(a);` `        ``RangeMaximumQuery rMaxQ = ``new` `RangeMaximumQuery();``        ``int``[] maxTree = rMaxQ.createSegmentTree(a);` `        ``int` `start = ``0``, end = ``0``;` `        ``// To store min and max in the current window``        ``int` `min, max;``        ``int` `maxValidLen = ``0``;` `        ``while` `(end < n) {``            ``min = rMimQ.rangeMinimumQuery(minTree,``                                          ``start, end, n);``            ``max = rMaxQ.rangeMaximumQuery(maxTree,``                                          ``start, end, n);``            ``if` `(``2` `* min <= max)``                ``start++;``            ``else``                ``maxValidLen = Math.max(maxValidLen,``                                       ``end - start + ``1``);``            ``end++;``        ``}``        ``return` `n - maxValidLen;``    ``}` `    ``class` `RangeMinimumQuery {` `        ``// Creates a new segment tree from``        ``// the given input array``        ``public` `int``[] createSegmentTree(``int``[] input)``        ``{``            ``int` `n = input.length;``            ``int` `segTreeSize = ``2` `* getNextPowerOfTwo(n) - ``1``;``            ``int``[] segmentTree = ``new` `int``[segTreeSize];` `            ``createSegmentTreeUtil(segmentTree, input,``                                  ``0``, n - ``1``, ``0``);``            ``return` `segmentTree;``        ``}` `        ``private` `void` `createSegmentTreeUtil(``int``[] segmentTree,``                                           ``int``[] input, ``int` `low,``                                           ``int` `high, ``int` `pos)``        ``{``            ``if` `(low == high) {` `                ``// Its a leaf node``                ``segmentTree[pos] = input[low];``                ``return``;``            ``}` `            ``// Construct left and right subtrees and then``            ``// update value for current node``            ``int` `mid = (low + high) / ``2``;``            ``createSegmentTreeUtil(segmentTree, input, low,``                                  ``mid, (``2` `* pos + ``1``));``            ``createSegmentTreeUtil(segmentTree, input,``                                  ``mid + ``1``, high, (``2` `* pos + ``2``));``            ``segmentTree[pos] = Math.min(segmentTree[``2` `* pos + ``1``],``                                        ``segmentTree[``2` `* pos + ``2``]);``        ``}` `        ``public` `int` `rangeMinimumQuery(``int``[] segmentTree, ``int` `from,``                                     ``int` `to, ``int` `inputSize)``        ``{``            ``return` `rangeMinimumQueryUtil(segmentTree, ``0``,``                                         ``inputSize - ``1``, from, to, ``0``);``        ``}` `        ``private` `int` `rangeMinimumQueryUtil(``int``[] segmentTree, ``int` `low,``                                        ``int` `high, ``int` `from, ``int` `to, ``int` `pos)``        ``{``            ``// Total overlap``            ``if` `(from <= low && to >= high) {``                ``return` `segmentTree[pos];``            ``}` `            ``// No overlap``            ``if` `(from > high || to < low) {``                ``return` `Integer.MAX_VALUE;``            ``}` `            ``// Partial overlap``            ``int` `mid = (low + high) / ``2``;``            ``int` `left = rangeMinimumQueryUtil(segmentTree, low,``                                             ``mid, from, to,``                                             ``(``2` `* pos + ``1``));``            ``int` `right = rangeMinimumQueryUtil(segmentTree,``                                              ``mid + ``1``, high, from,``                                              ``to, (``2` `* pos + ``2``));``            ``return` `Math.min(left, right);``        ``}``    ``}` `    ``class` `RangeMaximumQuery {` `        ``// Creates a new segment tree from given input array``        ``public` `int``[] createSegmentTree(``int``[] input)``        ``{``            ``int` `n = input.length;``            ``int` `segTreeSize = ``2` `* getNextPowerOfTwo(n) - ``1``;``            ``int``[] segmentTree = ``new` `int``[segTreeSize];` `            ``createSegmentTreeUtil(segmentTree, input, ``0``, n - ``1``, ``0``);``            ``return` `segmentTree;``        ``}` `        ``private` `void` `createSegmentTreeUtil(``int``[] segmentTree, ``int``[] input,``                                           ``int` `low, ``int` `high, ``int` `pos)``        ``{``            ``if` `(low == high) {` `                ``// Its a leaf node``                ``segmentTree[pos] = input[low];``                ``return``;``            ``}` `            ``// Construct left and right subtrees and then``            ``// update value for current node``            ``int` `mid = (low + high) / ``2``;``            ``createSegmentTreeUtil(segmentTree, input, low,``                                  ``mid, (``2` `* pos + ``1``));``            ``createSegmentTreeUtil(segmentTree, input,``                                  ``mid + ``1``, high, (``2` `* pos + ``2``));``            ``segmentTree[pos] = Math.max(segmentTree[``2` `* pos + ``1``],``                                        ``segmentTree[``2` `* pos + ``2``]);``        ``}` `        ``public` `int` `rangeMaximumQuery(``int``[] segmentTree,``                                     ``int` `from, ``int` `to, ``int` `inputSize)``        ``{``            ``return` `rangeMaximumQueryUtil(segmentTree, ``0``,``                                         ``inputSize - ``1``, from, to, ``0``);``        ``}` `        ``private` `int` `rangeMaximumQueryUtil(``int``[] segmentTree, ``int` `low,``                                 ``int` `high, ``int` `from, ``int` `to, ``int` `pos)``        ``{``            ``// Total overlap``            ``if` `(from <= low && to >= high) {``                ``return` `segmentTree[pos];``            ``}` `            ``// No overlap``            ``if` `(from > high || to < low) {``                ``return` `Integer.MIN_VALUE;``            ``}` `            ``// Partial overlap``            ``int` `mid = (low + high) / ``2``;``            ``int` `left = rangeMaximumQueryUtil(segmentTree, low,``                                             ``mid, from, to,``                                             ``(``2` `* pos + ``1``));``            ``int` `right = rangeMaximumQueryUtil(segmentTree,``                                              ``mid + ``1``, high, from,``                                              ``to, (``2` `* pos + ``2``));``            ``return` `Math.max(left, right);``        ``}``    ``}` `    ``// Function to return the minimum power of 2``    ``// which is greater than n``    ``private` `int` `getNextPowerOfTwo(``int` `n)``    ``{``        ``int` `logPart = (``int``)Math.ceil(Math.log(n)``                                     ``/ Math.log(``2``));``        ``return` `(``int``)Math.pow(``2``, logPart);``    ``}` `    ``// Driver code``    ``public` `static` `void` `main(String[] args)``    ``{``        ``int``[] a = { ``4``, ``5``, ``100``, ``9``, ``10``, ``11``, ``12``, ``15``, ``200` `};``        ``GFG gfg = ``new` `GFG();``        ``System.out.println(gfg.removeMinElements(a));``    ``}``}`

Python3

 `import` `math` `class` `GFG:``    ``# Function to return the minimum removals``    ``# required so that the array satisfies``    ``# the given condition``    ``def` `removeMinElements(``self``, a):``        ``n ``=` `len``(a)` `        ``rMimQ ``=` `self``.RangeMinimumQuery()``        ``minTree ``=` `rMimQ.createSegmentTree(a)` `        ``rMaxQ ``=` `self``.RangeMaximumQuery()``        ``maxTree ``=` `rMaxQ.createSegmentTree(a)` `        ``start ``=` `0``        ``end ``=` `0` `        ``# To store min and max in the current window``        ``min_val ``=` `0``        ``max_val ``=` `0``        ``maxValidLen ``=` `0` `        ``while` `end < n:``            ``min_val ``=` `rMimQ.rangeMinimumQuery(minTree, start, end, n)``            ``max_val ``=` `rMaxQ.rangeMaximumQuery(maxTree, start, end, n)``            ``if` `2` `*` `min_val <``=` `max_val:``                ``start ``+``=` `1``            ``else``:``                ``maxValidLen ``=` `max``(maxValidLen, end ``-` `start ``+` `1``)``            ``end ``+``=` `1``        ``return` `n ``-` `maxValidLen` `    ``class` `RangeMinimumQuery:``        ``def` `createSegmentTree(``self``, ``input``):``            ``n ``=` `len``(``input``)``            ``segTreeSize ``=` `2` `*` `self``.get_next_power_of_two(n) ``-` `1``            ``segmentTree ``=` `[``0``] ``*` `segTreeSize` `            ``self``.createSegmentTreeUtil(segmentTree, ``input``, ``0``, n ``-` `1``, ``0``)``            ``return` `segmentTree` `        ``def` `createSegmentTreeUtil(``self``, segmentTree, ``input``, low, high, pos):``            ``if` `low ``=``=` `high:``                ``# It's a leaf node``                ``segmentTree[pos] ``=` `input``[low]``                ``return` `            ``# Construct left and right subtrees and then``            ``# update value for the current node``            ``mid ``=` `(low ``+` `high) ``/``/` `2``            ``self``.createSegmentTreeUtil(segmentTree, ``input``, low, mid, (``2` `*` `pos ``+` `1``))``            ``self``.createSegmentTreeUtil(segmentTree, ``input``, mid ``+` `1``, high, (``2` `*` `pos ``+` `2``))``            ``segmentTree[pos] ``=` `min``(segmentTree[``2` `*` `pos ``+` `1``], segmentTree[``2` `*` `pos ``+` `2``])` `        ``def` `rangeMinimumQuery(``self``, segmentTree, from_, to, inputSize):``            ``return` `self``.rangeMinimumQueryUtil(segmentTree, ``0``, inputSize ``-` `1``, from_, to, ``0``)` `        ``def` `rangeMinimumQueryUtil(``self``, segmentTree, low, high, from_, to, pos):``            ``# Total overlap``            ``if` `from_ <``=` `low ``and` `to >``=` `high:``                ``return` `segmentTree[pos]` `            ``# No overlap``            ``if` `from_ > high ``or` `to < low:``                ``return` `float``(``'inf'``)` `            ``# Partial overlap``            ``mid ``=` `(low ``+` `high) ``/``/` `2``            ``left ``=` `self``.rangeMinimumQueryUtil(segmentTree, low, mid, from_, to, (``2` `*` `pos ``+` `1``))``            ``right ``=` `self``.rangeMinimumQueryUtil(segmentTree, mid ``+` `1``, high, from_, to, (``2` `*` `pos ``+` `2``))``            ``return` `min``(left, right)` `        ``# Move the get_next_power_of_two method here``        ``def` `get_next_power_of_two(``self``, n):``            ``log_part ``=` `math.ceil(math.log(n) ``/` `math.log(``2``))``            ``return` `2` `*``*` `log_part` `    ``class` `RangeMaximumQuery:``        ``# Move the get_next_power_of_two method here``        ``def` `get_next_power_of_two(``self``, n):``            ``log_part ``=` `math.ceil(math.log(n) ``/` `math.log(``2``))``            ``return` `2` `*``*` `log_part``            ` `        ``def` `createSegmentTree(``self``, ``input``):``            ``n ``=` `len``(``input``)``            ``segTreeSize ``=` `2` `*` `self``.get_next_power_of_two(n) ``-` `1``            ``segmentTree ``=` `[``0``] ``*` `segTreeSize` `            ``self``.createSegmentTreeUtil(segmentTree, ``input``, ``0``, n ``-` `1``, ``0``)``            ``return` `segmentTree` `        ``def` `createSegmentTreeUtil(``self``, segmentTree, ``input``, low, high, pos):``            ``if` `low ``=``=` `high:``                ``# It's a leaf node``                ``segmentTree[pos] ``=` `input``[low]``                ``return` `            ``# Construct left and right subtrees and then``            ``# update value for the current node``            ``mid ``=` `(low ``+` `high) ``/``/` `2``            ``self``.createSegmentTreeUtil(segmentTree, ``input``, low, mid, (``2` `*` `pos ``+` `1``))``            ``self``.createSegmentTreeUtil(segmentTree, ``input``, mid ``+` `1``, high, (``2` `*` `pos ``+` `2``))``            ``segmentTree[pos] ``=` `max``(segmentTree[``2` `*` `pos ``+` `1``], segmentTree[``2` `*` `pos ``+` `2``])` `        ``def` `rangeMaximumQuery(``self``, segmentTree, from_, to, inputSize):``            ``return` `self``.rangeMaximumQueryUtil(segmentTree, ``0``, inputSize ``-` `1``, from_, to, ``0``)` `        ``def` `rangeMaximumQueryUtil(``self``, segmentTree, low, high, from_, to, pos):``            ``# Total overlap``            ``if` `from_ <``=` `low ``and` `to >``=` `high:``                ``return` `segmentTree[pos]` `            ``# No overlap``            ``if` `from_ > high ``or` `to < low:``                ``return` `float``(``'-inf'``)` `            ``# Partial overlap``            ``mid ``=` `(low ``+` `high) ``/``/` `2``            ``left ``=` `self``.rangeMaximumQueryUtil(segmentTree, low, mid, from_, to, (``2` `*` `pos ``+` `1``))``            ``right ``=` `self``.rangeMaximumQueryUtil(segmentTree, mid ``+` `1``, high, from_, to, (``2` `*` `pos ``+` `2``))``            ``return` `max``(left, right)` `# Driver code``if` `__name__ ``=``=` `"__main__"``:``    ``a ``=` `[``4``, ``5``, ``100``, ``9``, ``10``, ``11``, ``12``, ``15``, ``200``]``    ``gfg ``=` `GFG()``    ``print``(gfg.removeMinElements(a))`

C#

 `// C# implementation of the approach``using` `System;` `class` `GFG``{` `    ``// Function to return the minimum removals``    ``// required so that the array satisfy``    ``// the given condition``    ``static` `int` `removeMinElements(``int``[] a)``    ``{``        ``int` `n = a.Length;` `        ``RangeMinimumQuery rMimQ = ``new` `RangeMinimumQuery();``        ``int``[] minTree = rMimQ.createSegmentTree(a);` `        ``RangeMaximumQuery rMaxQ = ``new` `RangeMaximumQuery();``        ``int``[] maxTree = rMaxQ.createSegmentTree(a);` `        ``int` `start = 0, end = 0;` `        ``// To store min and max in the current window``        ``int` `min, max;``        ``int` `maxValidLen = 0;` `        ``while` `(end < n) ``        ``{``            ``min = rMimQ.rangeMinimumQuery(minTree,``                                        ``start, end, n);``            ``max = rMaxQ.rangeMaximumQuery(maxTree,``                                        ``start, end, n);``            ``if` `(2 * min <= max)``                ``start++;``            ``else``                ``maxValidLen = Math.Max(maxValidLen,``                                    ``end - start + 1);``            ``end++;``        ``}``        ``return` `n - maxValidLen;``    ``}` `    ``class` `RangeMinimumQuery {` `        ``// Creates a new segment tree from``        ``// the given input array``        ``public` `int``[] createSegmentTree(``int``[] input)``        ``{``            ``int` `n = input.Length;``            ``int` `segTreeSize = 2 * getNextPowerOfTwo(n) - 1;``            ``int``[] segmentTree = ``new` `int``[segTreeSize];` `            ``createSegmentTreeUtil(segmentTree, input,``                                ``0, n - 1, 0);``            ``return` `segmentTree;``        ``}` `        ``public` `void` `createSegmentTreeUtil(``int``[] segmentTree,``                                        ``int``[] input, ``int` `low,``                                        ``int` `high, ``int` `pos)``        ``{``            ``if` `(low == high) {` `                ``// Its a leaf node``                ``segmentTree[pos] = input[low];``                ``return``;``            ``}` `            ``// Construct left and right subtrees and then``            ``// update value for current node``            ``int` `mid = (low + high) / 2;``            ``createSegmentTreeUtil(segmentTree, input, low,``                                ``mid, (2 * pos + 1));``            ``createSegmentTreeUtil(segmentTree, input,``                                ``mid + 1, high, (2 * pos + 2));``            ``segmentTree[pos] = Math.Min(segmentTree[2 * pos + 1],``                                        ``segmentTree[2 * pos + 2]);``        ``}` `        ``public` `int` `rangeMinimumQuery(``int``[] segmentTree, ``int` `from``,``                                    ``int` `to, ``int` `inputSize)``        ``{``            ``return` `rangeMinimumQueryUtil(segmentTree, 0,``                                        ``inputSize - 1, ``from``, to, 0);``        ``}` `        ``static` `int` `rangeMinimumQueryUtil(``int``[] segmentTree, ``int` `low,``                                        ``int` `high, ``int` `from``, ``int` `to, ``int` `pos)``        ``{``            ``// Total overlap``            ``if` `(``from` `<= low && to >= high) {``                ``return` `segmentTree[pos];``            ``}` `            ``// No overlap``            ``if` `(``from` `> high || to < low) {``                ``return` `int``.MaxValue;``            ``}` `            ``// Partial overlap``            ``int` `mid = (low + high) / 2;``            ``int` `left = rangeMinimumQueryUtil(segmentTree, low,``                                            ``mid, ``from``, to,``                                            ``(2 * pos + 1));``            ``int` `right = rangeMinimumQueryUtil(segmentTree,``                                            ``mid + 1, high, ``from``,``                                            ``to, (2 * pos + 2));``            ``return` `Math.Min(left, right);``        ``}``    ``}` `    ``class` `RangeMaximumQuery {` `        ``// Creates a new segment tree from given input array``        ``public` `int``[] createSegmentTree(``int``[] input)``        ``{``            ``int` `n = input.Length;``            ``int` `segTreeSize = 2 * getNextPowerOfTwo(n) - 1;``            ``int``[] segmentTree = ``new` `int``[segTreeSize];` `            ``createSegmentTreeUtil(segmentTree, input, 0, n - 1, 0);``            ``return` `segmentTree;``        ``}` `        ``public` `void` `createSegmentTreeUtil(``int``[] segmentTree, ``int``[] input,``                                        ``int` `low, ``int` `high, ``int` `pos)``        ``{``            ``if` `(low == high) {` `                ``// Its a leaf node``                ``segmentTree[pos] = input[low];``                ``return``;``            ``}` `            ``// Construct left and right subtrees and then``            ``// update value for current node``            ``int` `mid = (low + high) / 2;``            ``createSegmentTreeUtil(segmentTree, input, low,``                                ``mid, (2 * pos + 1));``            ``createSegmentTreeUtil(segmentTree, input,``                                ``mid + 1, high, (2 * pos + 2));``            ``segmentTree[pos] = Math.Max(segmentTree[2 * pos + 1],``                                        ``segmentTree[2 * pos + 2]);``        ``}` `        ``public` `int` `rangeMaximumQuery(``int``[] segmentTree,``                                    ``int` `from``, ``int` `to, ``int` `inputSize)``        ``{``            ``return` `rangeMaximumQueryUtil(segmentTree, 0,``                                        ``inputSize - 1, ``from``, to, 0);``        ``}` `        ``public` `int` `rangeMaximumQueryUtil(``int``[] segmentTree, ``int` `low,``                                ``int` `high, ``int` `from``, ``int` `to, ``int` `pos)``        ``{``            ``// Total overlap``            ``if` `(``from` `<= low && to >= high) {``                ``return` `segmentTree[pos];``            ``}` `            ``// No overlap``            ``if` `(``from` `> high || to < low) {``                ``return` `int``.MinValue;``            ``}` `            ``// Partial overlap``            ``int` `mid = (low + high) / 2;``            ``int` `left = rangeMaximumQueryUtil(segmentTree, low,``                                            ``mid, ``from``, to,``                                            ``(2 * pos + 1));``            ``int` `right = rangeMaximumQueryUtil(segmentTree,``                                            ``mid + 1, high, ``from``,``                                            ``to, (2 * pos + 2));``            ``return` `Math.Max(left, right);``        ``}``    ``}` `    ``// Function to return the minimum power of 2``    ``// which is greater than n``    ``static` `int` `getNextPowerOfTwo(``int` `n)``    ``{``        ``int` `logPart = (``int``)Math.Ceiling(Math.Log(n)``                                    ``/ Math.Log(2));``        ``return` `(``int``)Math.Pow(2, logPart);``    ``}` `    ``// Driver code``    ``public` `static` `void` `Main(String[] args)``    ``{``        ``int``[] a = { 4, 5, 100, 9, 10, 11, 12, 15, 200 };``        ``Console.WriteLine(removeMinElements(a));``    ``}``}` `// This code is contributed by Rajput-Ji`

Javascript

 `class GFG {``  ``removeMinElements(a) {``    ``const n = a.length;` `    ``// Create RangeMinimumQuery object``    ``const rMimQ = ``new` `RangeMinimumQuery();``    ``const minTree = rMimQ.createSegmentTree(a);` `    ``// Create RangeMaximumQuery object``    ``const rMaxQ = ``new` `RangeMaximumQuery();``    ``const maxTree = rMaxQ.createSegmentTree(a);` `    ``let start = 0;``    ``let end = 0;` `    ``// To store min and max in the current window``    ``let min_val = 0;``    ``let max_val = 0;``    ``let maxValidLen = 0;` `    ``while` `(end < n) {``      ``min_val = rMimQ.rangeMinimumQuery(minTree, start, end, n);``      ``max_val = rMaxQ.rangeMaximumQuery(maxTree, start, end, n);``      ``if` `(2 * min_val <= max_val) start++;``      ``else` `maxValidLen = Math.max(maxValidLen, end - start + 1);``      ``end++;``    ``}``    ``return` `n - maxValidLen;``  ``}``}` `class RangeMinimumQuery {``  ``createSegmentTree(input) {``    ``const n = input.length;``    ``const segTreeSize = 2 * ``this``.getNextPowerOfTwo(n) - 1;``    ``const segmentTree = Array(segTreeSize).fill(0);` `    ``this``.createSegmentTreeUtil(segmentTree, input, 0, n - 1, 0);``    ``return` `segmentTree;``  ``}` `  ``createSegmentTreeUtil(segmentTree, input, low, high, pos) {``    ``if` `(low === high) {``      ``// It's a leaf node``      ``segmentTree[pos] = input[low];``      ``return``;``    ``}` `    ``// Construct left and right subtrees and then``    ``// update value for the current node``    ``const mid = Math.floor((low + high) / 2);``    ``this``.createSegmentTreeUtil(segmentTree, input, low, mid, 2 * pos + 1);``    ``this``.createSegmentTreeUtil(segmentTree, input, mid + 1, high, 2 * pos + 2);``    ``segmentTree[pos] = Math.min(segmentTree[2 * pos + 1], segmentTree[2 * pos + 2]);``  ``}` `  ``rangeMinimumQuery(segmentTree, from, to, inputSize) {``    ``return` `this``.rangeMinimumQueryUtil(segmentTree, 0, inputSize - 1, from, to, 0);``  ``}` `  ``rangeMinimumQueryUtil(segmentTree, low, high, from, to, pos) {``    ``// Total overlap``    ``if` `(from <= low && to >= high) {``      ``return` `segmentTree[pos];``    ``}` `    ``// No overlap``    ``if` `(from > high || to < low) {``      ``return` `Infinity;``    ``}` `    ``// Partial overlap``    ``const mid = Math.floor((low + high) / 2);``    ``const left = ``this``.rangeMinimumQueryUtil(segmentTree, low, mid, from, to, 2 * pos + 1);``    ``const right = ``this``.rangeMinimumQueryUtil(segmentTree, mid + 1, high, from, to, 2 * pos + 2);``    ``return` `Math.min(left, right);``  ``}` `  ``getNextPowerOfTwo(n) {``    ``const logPart = Math.ceil(Math.log2(n));``    ``return` `2 ** logPart;``  ``}``}` `class RangeMaximumQuery {``  ``createSegmentTree(input) {``    ``const n = input.length;``    ``const segTreeSize = 2 * ``this``.getNextPowerOfTwo(n) - 1;``    ``const segmentTree = Array(segTreeSize).fill(0);` `    ``this``.createSegmentTreeUtil(segmentTree, input, 0, n - 1, 0);``    ``return` `segmentTree;``  ``}` `  ``createSegmentTreeUtil(segmentTree, input, low, high, pos) {``    ``if` `(low === high) {``      ``// It's a leaf node``      ``segmentTree[pos] = input[low];``      ``return``;``    ``}` `    ``// Construct left and right subtrees and then``    ``// update value for the current node``    ``const mid = Math.floor((low + high) / 2);``    ``this``.createSegmentTreeUtil(segmentTree, input, low, mid, 2 * pos + 1);``    ``this``.createSegmentTreeUtil(segmentTree, input, mid + 1, high, 2 * pos + 2);``    ``segmentTree[pos] = Math.max(segmentTree[2 * pos + 1], segmentTree[2 * pos + 2]);``  ``}` `  ``rangeMaximumQuery(segmentTree, from, to, inputSize) {``    ``return` `this``.rangeMaximumQueryUtil(segmentTree, 0, inputSize - 1, from, to, 0);``  ``}` `  ``rangeMaximumQueryUtil(segmentTree, low, high, from, to, pos) {``    ``// Total overlap``    ``if` `(from <= low && to >= high) {``      ``return` `segmentTree[pos];``    ``}` `    ``// No overlap``    ``if` `(from > high || to < low) {``      ``return` `-Infinity;``    ``}` `    ``// Partial overlap``    ``const mid = Math.floor((low + high) / 2);``    ``const left = ``this``.rangeMaximumQueryUtil(segmentTree, low, mid, from, to, 2 * pos + 1);``    ``const right = ``this``.rangeMaximumQueryUtil(segmentTree, mid + 1, high, from, to, 2 * pos + 2);``    ``return` `Math.max(left, right);``  ``}` `  ``getNextPowerOfTwo(n) {``    ``const logPart = Math.ceil(Math.log2(n));``    ``return` `2 ** logPart;``  ``}``}` `const gfg = ``new` `GFG();``const a = [4, 5, 100, 9, 10, 11, 12, 15, 200];``console.log(gfg.removeMinElements(a));`

Output
```4

```

Previous
Next