给定n个整数和整数k的未排序数组arr [] ,任务是在给定的索引范围[l,r]中找到第k个最大元素
例子:
Input: arr[] = {5, 3, 2, 4, 1}, k = 4, l = 1, r = 5
Output: 4
4 will be the 4th element when arr[0…4] is sorted.
Input: arr[] = {1, 4, 2, 3, 5, 7, 6}, k = 3, l = 3, r = 6
Output: 5
方法:一个简单的解决方案是将范围内的元素排序并获得第k个最大元素,该解决方案的时间复杂度将是每个查询的nlog(n) 。我们可以使用前缀数组和二进制搜索来解决log(n)中的每个查询。我们要做的就是维护一个2d前缀数组,其中第i行将包含与给定数组相同范围内小于等于i的元素数量。完成前缀数组后,我们需要做的就是对前缀数组进行简单的二进制搜索。因此,时间复杂度大大降低了。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
#define MAX 1001
static int prefix[MAX][MAX];
int ar[MAX];
// Function to calculate the prefix
void cal_prefix(int n, int arr[])
{
int i, j;
// Creating one based indexing
for (i = 0; i < n; i++)
ar[i + 1] = arr[i];
// Initilizing and creating prefix array
for (i = 1; i <= 1000; i++) {
for (j = 0; j <= n; j++)
prefix[i][j] = 0;
for (j = 1; j <= n; j++) {
// Creating a prefix array for every
// possible value in a given range
prefix[i][j] = prefix[i][j - 1]
+ (int)(ar[j] <= i ? 1 : 0);
}
}
}
// Function to return the kth largest element
// in the index range [l, r]
int ksub(int l, int r, int n, int k)
{
int lo, hi, mid;
lo = 1;
hi = 1000;
// Binary searching through the 2d array
// and only checking the range in which
// the sub array is a part
while (lo + 1 < hi) {
mid = (lo + hi) / 2;
if (prefix[mid][r] - prefix[mid][l - 1] >= k)
hi = mid;
else
lo = mid + 1;
}
if (prefix[lo][r] - prefix[lo][l - 1] >= k)
hi = lo;
return hi;
}
// Driver code
int main()
{
int arr[] = { 1, 4, 2, 3, 5, 7, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
int k = 4;
// Creating the prefix array
// for the given array
cal_prefix(n, arr);
// Queries
int queries[][3] = { { 1, n, 1 },
{ 2, n - 2, 2 },
{ 3, n - 1, 3 } };
int q = sizeof(queries) / sizeof(queries[0]);
// Perform queries
for (int i = 0; i < q; i++)
cout << ksub(queries[i][0], queries[i][1],
n, queries[i][2])
<< endl;
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG
{
static int MAX = 1001;
static int prefix[][] = new int[MAX][MAX];
static int ar[] = new int[MAX];
// Function to calculate the prefix
static void cal_prefix(int n, int arr[])
{
int i, j;
// Creating one based indexing
for (i = 0; i < n; i++)
ar[i + 1] = arr[i];
// Initilizing and creating prefix array
for (i = 1; i <= 1000; i++)
{
for (j = 0; j <= n; j++)
prefix[i][j] = 0;
for (j = 1; j <= n; j++)
{
// Creating a prefix array for every
// possible value in a given range
prefix[i][j] = prefix[i][j - 1]
+ (int)(ar[j] <= i ? 1 : 0);
}
}
}
// Function to return the kth largest element
// in the index range [l, r]
static int ksub(int l, int r, int n, int k)
{
int lo, hi, mid;
lo = 1;
hi = 1000;
// Binary searching through the 2d array
// and only checking the range in which
// the sub array is a part
while (lo + 1 < hi)
{
mid = (lo + hi) / 2;
if (prefix[mid][r] - prefix[mid][l - 1] >= k)
hi = mid;
else
lo = mid + 1;
}
if (prefix[lo][r] - prefix[lo][l - 1] >= k)
hi = lo;
return hi;
}
// Driver code
public static void main(String args[])
{
int arr[] = { 1, 4, 2, 3, 5, 7, 6 };
int n = arr.length;
int k = 4;
// Creating the prefix array
// for the given array
cal_prefix(n, arr);
// Queries
int queries[][] = { { 1, n, 1 },
{ 2, n - 2, 2 },
{ 3, n - 1, 3 } };
int q = queries.length;
// Perform queries
for (int i = 0; i < q; i++)
System.out.println( ksub(queries[i][0], queries[i][1],
n, queries[i][2]));
}
}
// This code is contributed by Arnab Kundu
Python3
# Python3 implementation of the approach
MAX = 1001
prefix = [[0 for i in range(MAX)]
for j in range(MAX)]
ar = [0 for i in range(MAX)]
# Function to calculate the prefix
def cal_prefix(n, arr):
# Creating one based indexing
for i in range(n):
ar[i + 1] = arr[i]
# Initilizing and creating prefix array
for i in range(1, 1001, 1):
for j in range(n + 1):
prefix[i][j] = 0
for j in range(1, n + 1):
# Creating a prefix array for every
# possible value in a given range
if ar[j] <= i:
k = 1
else:
k = 0
prefix[i][j] = prefix[i][j - 1] + k
# Function to return the kth largest element
# in the index range [l, r]
def ksub(l, r, n, k):
lo = 1
hi = 1000
# Binary searching through the 2d array
# and only checking the range in which
# the sub array is a part
while (lo + 1 < hi):
mid = int((lo + hi) / 2)
if (prefix[mid][r] -
prefix[mid][l - 1] >= k):
hi = mid
else:
lo = mid + 1
if (prefix[lo][r] -
prefix[lo][l - 1] >= k):
hi = lo
return hi
# Driver code
if __name__ == '__main__':
arr = [1, 4, 2, 3, 5, 7, 6]
n = len(arr)
k = 4
# Creating the prefix array
# for the given array
cal_prefix(n, arr)
# Queries
queries = [[1, n, 1],
[2, n - 2, 2],
[3, n - 1, 3]]
q = len(queries)
# Perform queries
for i in range(q):
print(ksub(queries[i][0],
queries[i][1], n, queries[i][2]))
# This code is contributed by
# Surendra_Gangwar
C#
// C# implementation of the approach
using System;
class GFG
{
static int MAX = 1001;
static int[,] prefix = new int[MAX,MAX];
static int[] ar = new int[MAX];
// Function to calculate the prefix
static void cal_prefix(int n, int[] arr)
{
int i, j;
// Creating one based indexing
for (i = 0; i < n; i++)
ar[i + 1] = arr[i];
// Initilizing and creating prefix array
for (i = 1; i <= 1000; i++)
{
for (j = 0; j <= n; j++)
prefix[i, j] = 0;
for (j = 1; j <= n; j++)
{
// Creating a prefix array for every
// possible value in a given range
prefix[i, j] = prefix[i, j - 1]
+ (int)(ar[j] <= i ? 1 : 0);
}
}
}
// Function to return the kth largest element
// in the index range [l, r]
static int ksub(int l, int r, int n, int k)
{
int lo, hi, mid;
lo = 1;
hi = 1000;
// Binary searching through the 2d array
// and only checking the range in which
// the sub array is a part
while (lo + 1 < hi)
{
mid = (lo + hi) / 2;
if (prefix[mid, r] - prefix[mid, l - 1] >= k)
hi = mid;
else
lo = mid + 1;
}
if (prefix[lo, r] - prefix[lo, l - 1] >= k)
hi = lo;
return hi;
}
// Driver code
static void Main()
{
int []arr = { 1, 4, 2, 3, 5, 7, 6 };
int n = arr.Length;
//int k = 4;
// Creating the prefix array
// for the given array
cal_prefix(n, arr);
// Queries
int [,]queries = { { 1, n, 1 },
{ 2, n - 2, 2 },
{ 3, n - 1, 3 } };
int q = queries.Length/queries.Rank-1;
// Perform queries
for (int i = 0; i < q; i++)
Console.WriteLine( ksub(queries[i,0], queries[i,1],
n, queries[i, 2]));
}
}
// This code is contributed by mits
PHP
= $k)
$hi = $mid;
else
$lo = $mid + 1;
}
if ($prefix[$lo][$r] - $prefix[$lo][$l - 1] >= $k)
$hi = $lo;
return $hi;
}
// Driver code
$arr = array( 1, 4, 2, 3, 5, 7, 6 );
$n = count($arr);
$k = 4;
// Creating the prefix array
// for the given array
cal_prefix($n, $arr);
// Queries
$queries = array(array( 1, $n, 1 ),
array( 2, $n - 2, 2 ),
array( 3, $n - 1, 3 ));
$q = count($queries);
// Perform queries
for ($i = 0; $i < $q; $i++)
echo ksub($queries[$i][0], $queries[$i][1],$n, $queries[$i][2])."\n";
// This code is contributed by mits
?>
输出:
1
3
5