0% completed
You are given an array nums
containing n
integers and a 2D array queries
of length q
, where queries[i] = [start<sub>i</sub>, end<sub>i</sub>], representing a starting and ending range (inclusive).
Return an array of size q
, where each element is the minimum
value in the respective range from nums
.
Example 1:
[0, 3]
, the minimum is 1
.[2, 5]
, the minimum is 1
.[0, 1]
, the minimum is 2
.[3, 7]
, the minimum is 3
.[0, 7]
, the minimum is 1
.[4, 6]
, the minimum is 3
.[4, 5]
, the minimum is 5
.Example 2:
[1, 3]
, the minimum is 2
.[0, 2]
, the minimum is 4
.[2, 4]
, the minimum is 2
.[3, 5]
, the minimum is 2
.Example 3:
[0, 4]
, the minimum is 5
.[1, 3]
, the minimum is 5
.[2, 5]
, the minimum is 5
.[3, 6]
, the minimum is 7
.Constraints:
To solve this problem, we will use a Segment Tree. A Segment Tree is a data structure that allows answering range queries in logarithmic time. The idea is to build a binary tree where each node represents a segment (or interval) of the array. The leaf nodes represent single elements, and the internal nodes store the minimum value of their respective children. This way, querying for the minimum value in any range can be done efficiently.
We will first construct the Segment Tree from the given array. This construction takes O(n) time. Once the tree is built, we can answer any range minimum query in O(log n) time. For each query, we will traverse the tree to find the minimum value in the specified range.
Compute Height and Maximum Size:
ceil(log2(n))
. This gives the number of levels needed to cover all elements of the array.2 * (2^height) - 1
. This size ensures enough space for all nodes in the tree.Build the Segment Tree:
nums
, i.e., from segmentStart = 0
to segmentEnd = n-1
.segmentStart == segmentEnd
), store the value of that element in the current node of the segment tree.mid = segmentStart + (segmentEnd - segmentStart) / 2
.[segmentStart, mid]
.[mid + 1, segmentEnd]
.segmentTree[index] = Math.min(segmentTree[leftChildIndex], segmentTree[rightChildIndex])
.[queryStart, queryEnd]
, start from the root node representing the range [0, n-1]
.Integer.MAX_VALUE
).[segmentStart, mid]
.[mid + 1, segmentEnd]
.Let's consider the input [2, 6, 1, 12, 9, 5, 3, 7]
.
Initialization:
n = 8
, the height of the segment tree is ceil(log2(8)) = 3
.2 * (2^3) - 1 = 15
.segmentTree = new int[15]
with all values set to Integer.MAX_VALUE
.Building the Tree:
mid = 0 + (7 - 0) / 2 = 3
mid = 0 + (3 - 0) / 2 = 1
mid = 0 + (1 - 0) / 2 = 0
segmentTree[7] = nums[0] = 2
segmentTree[8] = nums[1] = 6
segmentTree[3] = Math.min(segmentTree[7], segmentTree[8]) = Math.min(2, 6) = 2
mid = 2 + (3 - 2) / 2 = 2
segmentTree[9] = nums[2] = 1
segmentTree[10] = nums[3] = 12
segmentTree[4] = Math.min(segmentTree[9], segmentTree[10]) = Math.min(1, 12) = 1
segmentTree[1] = Math.min(segmentTree[3], segmentTree[4]) = Math.min(2, 1) = 1
mid = 4 + (7 - 4) / 2 = 5
mid = 4 + (5 - 4) / 2 = 4
segmentTree[11] = nums[4] = 9
segmentTree[12] = nums[5] = 5
segmentTree[5] = Math.min(segmentTree[11], segmentTree[12]) = Math.min(9, 5) = 5
mid = 6 + (7 - 6) / 2 = 6
segmentTree[13] = nums[6] = 3
segmentTree[14] = nums[7] = 7
segmentTree[6] = Math.min(segmentTree[13], segmentTree[14]) = Math.min(3, 7) = 3
segmentTree[2] = Math.min(segmentTree[5], segmentTree[6]) = Math.min(5, 3) = 3
segmentTree[0] = Math.min(segmentTree[1], segmentTree[2]) = Math.min(1, 3) = 1
The segment tree is `[1, 1, 3, 2, 1, 5, 3, 2, 6, 1, 12, 9, 5, 3, 7]Query [0, 3]:
segmentTree[1] = 1
1
Query [2, 5]:
segmentTree[4] = 1
segmentTree[5] = 5
min(1,5) = 1
1
Segment Tree Construction: O(n)
Range Minimum Query: O(q*log n)
q
queries, the total time complexity is the O(q*log n).Overall Time Complexity: O(n) + O(q log n)
q
range minimum queries.nums
. The segment tree array's size is approximately 2 * 2<sup>log n</sup> - 1, which simplifies to O(n)......
.....
.....