给定一个数组arr[]和一个整数K ,任务是找到每个大小为K 的连续子数组的最大值。
例子:
Input: arr[] = {1, 2, 3, 1, 4, 5, 2, 3, 6}, K = 3
Output: 3 3 4 5 5 5 6
Explanation:
Maximum of 1, 2, 3 is 3
Maximum of 2, 3, 1 is 3
Maximum of 3, 1, 4 is 4
Maximum of 1, 4, 5 is 5
Maximum of 4, 5, 2 is 5
Maximum of 5, 2, 3 is 5
Maximum of 2, 3, 6 is 6
Input: arr[] = {8, 5, 10, 7, 9, 4, 15, 12, 90, 13}, K = 4
Output: 10 10 10 15 15 90 90
Explanation:
Maximum of first 4 elements is 10, similarly for next 4
elements (i.e from index 1 to 4) is 10, So the sequence
generated is 10 10 10 15 15 90 90
方法:
这个想法是使用 Segment 树来回答所有大小为 K 的子数组的最大值。
- 段树的表示
- 叶节点是输入数组的元素。
- 每个内部节点代表其所有子节点的最大值。
- 从给定数组构建段树:
- 我们从一个段 arr[0 开始。 . . n-1],并且每次我们将当前段分成两半(如果它还没有变成长度为1的段),然后在两半上调用相同的过程,对于每个这样的段,我们存储最大值段树节点中的值。
- 除最后一层外,构建的线段树的所有层都将被完全填充。此外,这棵树将是一个完整的二叉树,因为我们总是在每一层将段分成两半。
- 由于构造的树总是一棵有 n 个叶子的完全二叉树,因此会有 n-1 个内部节点。所以总节点数将为 2 * n – 1。
- 段树的高度将为log 2 n 。
- 由于树是使用数组表示的,并且必须保持父子索引之间的关系,因此为段树分配的内存大小将为2 *(2 ceil(log 2 n) )-1 。
下面是上述方法的实现。
C++
// C++ program to answer Maximum
// of allsubarrays of size k
// using segment tree
#include
using namespace std;
#define MAX 1000000
// Size of segment
// tree = 2^{log(MAX)+1}
int st[3 * MAX];
// A utility function to get the
// middle index of given range.
int getMid(int s, int e)
{
return s + (e - s) / 2;
}
// A recursive function that
// constructs Segment Tree for
// array[s...e]. node is index
// of current node in segment
// tree st
void constructST(int node, int s,
int e, int arr[])
{
// If there is one element in
// array, store it in current
// node of segment tree and return
if (s == e) {
st[node] = arr[s];
return;
}
// If there are more than
// one elements, then recur
// for left and right subtrees
// and store the max of
// values in this node
int mid = getMid(s, e);
constructST(2 * node, s,
mid, arr);
constructST(2 * node + 1,
mid + 1, e,
arr);
st[node] = max(st[2 * node],
st[2 * node + 1]);
}
/* A recursive function to get the
maximum of range[l, r] The
following paramaters for
this function:
st -> Pointer to segment tree
node -> Index of current node in
the segment tree .
s & e -> Starting and ending indexes
of the segment represented
by current node, i.e., st[node]
l & r -> Starting and ending indexes
of range query
*/
int getMax(int node, int s,
int e, int l,
int r)
{
// If segment of this node
// does not belong to
// given range
if (s > r || e < l)
return INT_MIN;
// If segment of this node
// is completely part of
// given range, then return
// the max of segment
if (s >= l && e <= r)
return st[node];
// If segment of this node
// is partially the part
// of given range
int mid = getMid(s, e);
return max(getMax(2 * node,
s, mid,
l, r),
getMax(2 * node + 1,
mid + 1, e,
l, r));
}
// Function to print the max
// of all subarrays of size k
void printKMax(int n, int k)
{
for (int i = 0; i < n; i++) {
if ((k - 1 + i) < n)
cout << getMax(1, 0, n - 1,
i, k - 1 + i)
<< " ";
else
break;
}
}
// Driver code
int main()
{
int k = 4;
int arr[] = { 8, 5, 10, 7, 9, 4, 15,
12, 90, 13 };
int n = sizeof(arr) / sizeof(arr[0]);
// Function to construct the
// segment tree
constructST(1, 0, n - 1, arr);
printKMax(n, k);
return 0;
}
Java
// Java program to answer Maximum
// of allsubarrays of size k
// using segment tree
import java.io.*;
import java.util.*;
class GFG{
static int MAX = 1000000;
// Size of segment
// tree = 2^{log(MAX)+1}
static int[] st = new int[3 * MAX];
// A utility function to get the
// middle index of given range.
static int getMid(int s, int e)
{
return s + (e - s) / 2;
}
// A recursive function that
// constructs Segment Tree for
// array[s...e]. node is index
// of current node in segment
// tree st
static void constructST(int node, int s,
int e, int[] arr)
{
// If there is one element in
// array, store it in current
// node of segment tree and return
if (s == e)
{
st[node] = arr[s];
return;
}
// If there are more than
// one elements, then recur
// for left and right subtrees
// and store the max of
// values in this node
int mid = getMid(s, e);
constructST(2 * node, s, mid, arr);
constructST(2 * node + 1,
mid + 1, e, arr);
st[node] = Math.max(st[2 * node],
st[2 * node + 1]);
}
/* A recursive function to get the
maximum of range[l, r] The
following paramaters for
this function:
st -> Pointer to segment tree
node -> Index of current node in
the segment tree .
s & e -> Starting and ending indexes
of the segment represented
by current node, i.e., st[node]
l & r -> Starting and ending indexes
of range query
*/
static int getMax(int node, int s, int e,
int l, int r)
{
// If segment of this node
// does not belong to
// given range
if (s > r || e < l)
return Integer.MIN_VALUE;
// If segment of this node
// is completely part of
// given range, then return
// the max of segment
if (s >= l && e <= r)
return st[node];
// If segment of this node
// is partially the part
// of given range
int mid = getMid(s, e);
return Math.max(getMax(2 * node, s,
mid, l, r),
getMax(2 * node + 1,
mid + 1, e, l, r));
}
// Function to print the max
// of all subarrays of size k
static void printKMax(int n, int k)
{
for(int i = 0; i < n; i++)
{
if ((k - 1 + i) < n)
System.out.print(getMax(1, 0, n - 1,
i, k - 1 + i) + " ");
else
break;
}
}
// Driver code
public static void main(String[] args)
{
int k = 4;
int[] arr = { 8, 5, 10, 7, 9,
4, 15, 12, 90, 13 };
int n = arr.length;
// Function to construct the
// segment tree
constructST(1, 0, n - 1, arr);
printKMax(n, k);
}
}
// This code is contributed by akhilsaini
Python3
# Python3 program to answer maximum
# of all subarrays of size k
# using segment tree
import sys
MAX = 1000000
# Size of segment
# tree = 2^{log(MAX)+1}
st = [0] * (3 * MAX)
# A utility function to get the
# middle index of given range.
def getMid(s, e):
return s + (e - s) // 2
# A recursive function that
# constructs Segment Tree for
# array[s...e]. node is index
# of current node in segment
# tree st
def constructST(node, s, e, arr):
# If there is one element in
# array, store it in current
# node of segment tree and return
if (s == e):
st[node] = arr[s]
return
# If there are more than
# one elements, then recur
# for left and right subtrees
# and store the max of
# values in this node
mid = getMid(s, e)
constructST(2 * node, s, mid, arr)
constructST(2 * node + 1, mid + 1, e, arr)
st[node] = max(st[2 * node], st[2 * node + 1])
''' A recursive function to get the
maximum of range[l, r] The
following paramaters for
this function:
st -> Pointer to segment tree
node -> Index of current node in
the segment tree .
s & e -> Starting and ending indexes
of the segment represented
by current node, i.e., st[node]
l & r -> Starting and ending indexes
of range query
'''
def getMax(node, s, e, l, r):
# If segment of this node
# does not belong to
# given range
if (s > r or e < l):
return (-sys.maxsize - 1)
# If segment of this node
# is completely part of
# given range, then return
# the max of segment
if (s >= l and e <= r):
return st[node]
# If segment of this node
# is partially the part
# of given range
mid = getMid(s, e)
return max(getMax(2 * node, s, mid, l, r),
getMax(2 * node + 1, mid + 1, e, l, r))
# Function to print the max
# of all subarrays of size k
def printKMax(n, k):
for i in range(n):
if ((k - 1 + i) < n):
print(getMax(1, 0, n - 1, i,
k - 1 + i), end = " ")
else:
break
# Driver code
if __name__ == "__main__":
k = 4
arr = [ 8, 5, 10, 7, 9, 4, 15, 12, 90, 13 ]
n = len(arr)
# Function to construct the
# segment tree
constructST(1, 0, n - 1, arr)
printKMax(n, k)
# This code is contributed by chitranayal
C#
// C# program to answer Maximum
// of allsubarrays of size k
// using segment tree
using System;
class GFG{
static int MAX = 1000000;
// Size of segment
// tree = 2^{log(MAX)+1}
static int[] st = new int[3 * MAX];
// A utility function to get the
// middle index of given range.
static int getMid(int s, int e)
{
return s + (e - s) / 2;
}
// A recursive function that
// constructs Segment Tree for
// array[s...e]. node is index
// of current node in segment
// tree st
static void constructST(int node, int s,
int e, int[] arr)
{
// If there is one element in
// array, store it in current
// node of segment tree and return
if (s == e)
{
st[node] = arr[s];
return;
}
// If there are more than
// one elements, then recur
// for left and right subtrees
// and store the max of
// values in this node
int mid = getMid(s, e);
constructST(2 * node, s, mid, arr);
constructST(2 * node + 1, mid + 1, e, arr);
st[node] = Math.Max(st[2 * node],
st[2 * node + 1]);
}
/* A recursive function to get the
maximum of range[l, r] The
following paramaters for
this function:
st -> Pointer to segment tree
node -> Index of current node in
the segment tree .
s & e -> Starting and ending indexes
of the segment represented
by current node, i.e., st[node]
l & r -> Starting and ending indexes
of range query
*/
static int getMax(int node, int s, int e,
int l, int r)
{
// If segment of this node
// does not belong to
// given range
if (s > r || e < l)
return int.MinValue;
// If segment of this node
// is completely part of
// given range, then return
// the max of segment
if (s >= l && e <= r)
return st[node];
// If segment of this node
// is partially the part
// of given range
int mid = getMid(s, e);
return Math.Max(getMax(2 * node, s,
mid, l, r),
getMax(2 * node + 1,
mid + 1, e, l, r));
}
// Function to print the max
// of all subarrays of size k
static void printKMax(int n, int k)
{
for(int i = 0; i < n; i++)
{
if ((k - 1 + i) < n)
Console.Write(getMax(1, 0, n - 1,
i, k - 1 + i) + " ");
else
break;
}
}
// Driver code
public static void Main()
{
int k = 4;
int[] arr = { 8, 5, 10, 7, 9,
4, 15, 12, 90, 13 };
int n = arr.Length;
// Function to construct the
// segment tree
constructST(1, 0, n - 1, arr);
printKMax(n, k);
}
}
// This code is contributed by akhilsaini
Javascript
10 10 10 15 15 90 90
时间复杂度: O(N * log K)
相关文章:滑动窗口最大值(所有大小为 k 的子数组的最大值)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live