给定由N个整数和整数K组成的两个数组A []和B [] ,任务是找到B [i] + B [j] + abs(A [i] – A [j])的最大值通过选择任意对(i,j)使得abs(A [i] – A [j])≤K 。
例子:
Input: A[] = {5, 6, 9, 10}, B[] = {3, 0, 10, -10}, K = 1
Output: 4
Explanation:
Only two pairs can be chosen, i.e. (0, 1) and (2, 3), because abs(A[0] – A[1]) ≤ K and abs(A[2] – A[3]) ≤ K.
The value of (0, 1) pair is B[0] + B[1] + abs(A[0] – A[1]) = 3 + 0 + 1 = 4.
The value of (2, 3) pair is B[2] + B[3] + abs(A[2] – A[3]) = 10 + (-10) + 1 = 1.
Hence, the maximum value from all possible pairs is 4.
Input: A[] = {1, 2, 3, 4}, B[] = {0, 8, 6, 9}, K = 2
Output: 19
天真的方法:最简单的方法是从给定数组生成所有可能的对,并对满足给定条件的那些对进行计数。检查所有对后,打印所有对的计数。
时间复杂度: O(N 2 )
辅助空间: O(N)
高效方法:为了优化上述方法,其思想是根据数组A []的值使用段树,二进制搜索和数组排序。从给定的方程式中可以明显看出B [i] + B [j] + abs(A [i] – A [j])等于以下任何一个值:
- B [i] + B [j] +(A [i] – A [j])
- B [i] + B [j] +(A [j] – A [i])
Consider 2nd equation:
B[i] + B[j] + A[j] – A[i] = B[i] – A[i] + (B[j] + A[j])
- Here, it is observed that for each i in the array A[], finding the right most index of value smaller than of equal to A[i] + K. Let the rightmost index be right.
- Now, calculate B[i] – A[i] + max value of B[j] + A[j] where i + 1 <= j <= right. This will give the maximum value of selected pair.
- To calculate the maximum value each time in a range, segment trees can be used.
请按照以下步骤解决问题:
- 根据数组A []的值对所有值B [i]和B [i] + A [i]进行排序。
- 将maxValue初始化为INT_MIN以存储最终的最大答案,并初始化存储所有值A [i] + B [i]的范围最大查询段树。
- 遍历数组A []并执行以下操作:
- 对于每个元素,找到索引,说正确,使用二进制搜索使abs(A [i] – A [right])<=K 。
- 然后,找到(A [j] + B [j])的最大值,其中i + 1 <= j <= right 。
- 更新包括maxValue作为包括maxValue = MAX(包括maxValue,B [Ⅰ] – A [1] + A [J] + B [j])。
- 完成上述步骤后,输出maxValue的值作为结果。
下面是上述方法的实现:
Java
// Java program for the above approach
import java.util.*;
// Clas to store the values of a[i],
// b[i], a[i] + b[i]
class triplet implements Comparable {
int a, b, c;
// Constructor
triplet(int a, int b, int c)
{
this.a = a;
this.b = b;
this.c = c;
}
// Sort values according to array
public int compareTo(triplet o)
{
return this.a - o.a;
}
}
class GFG {
// Stores the segment tree
static int seg[];
// Function to find the maximum
// possible value according to the
// given condition
public static void maxValue(
int a[], int b[], int n, int k)
{
// Initialize triplet array
triplet arr[] = new triplet[n];
// Store the values a[i], b[i],
// a[i] + b[i]
for (int i = 0; i < n; i++) {
arr[i] = new triplet(a[i], b[i],
a[i] + b[i]);
}
// Sort the array according
// to array a[]
Arrays.sort(arr);
// Build segment tree
seg = new int[4 * n];
build(arr, 0, 0, n - 1);
// Intialise the maxvalue of
// the selected pairs
int maxvalue = Integer.MIN_VALUE;
// Traverse the array
for (int i = 0; i < n; i++) {
// For each value find the
// floor(arr[i] + k)
int right = search(arr,
arr[i].a + k);
// Find the maximum value of
// the select pairs i and max
// from (i + 1, right)
if (right != -1) {
maxvalue = Math.max(
maxvalue, arr[i].b - arr[i].a
+ getMax(arr, 0, 0, n - 1,
i + 1, right));
}
}
// Print the maximum value
System.out.println(maxvalue);
}
// Function to search floor of
// the current value
public static int search(
triplet arr[], int val)
{
// Initialise low and high values
int low = 0, high = arr.length - 1;
int ans = -1;
// Perform Binary Search
while (low <= high) {
int mid = low + (high - low) / 2;
// If the current value is
// <= val then store the
// candidate answer and
// find for rigtmost one
if (arr[mid].a <= val) {
ans = mid;
low = mid + 1;
}
else
high = mid - 1;
}
return ans;
}
// Function to build segment tree
public static void build(
triplet arr[], int index,
int s, int e)
{
// Base Case
if (s == e) {
seg[index] = arr[s].c;
return;
}
int mid = s + (e - s) / 2;
// Build the left and right
// segment trees
build(arr, 2 * index + 1, s, mid);
build(arr, 2 * index + 2, mid + 1, e);
// Update current index
seg[index] = Math.max(seg[2 * index + 1],
seg[2 * index + 2]);
}
// Function to get maximum value
// in the range [qs, qe]
public static int getMax(
triplet arr[], int index, int s,
int e, int qs, int qe)
{
// If segement is not in range
if (qe < s || e < qs)
return Integer.MIN_VALUE / 2;
// If segement is completely
// inside the query
if (s >= qs && e <= qe)
return seg[index];
// Calcualate the maximum value
// in left and right half
int mid = s + (e - s) / 2;
return Math.max(
getMax(arr, 2 * index + 1,
s, mid, qs, qe),
getMax(arr, 2 * index + 2,
mid + 1, e, qs, qe));
}
// Driver Code
public static void main(String args[])
{
int N = 4, K = 1;
int A[] = { 5, 6, 9, 10 };
int B[] = { 3, 0, 10, -10 };
// Function call
maxValue(A, B, N, K);
}
}
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
// Clas to store the values of a[i],
// b[i], a[i] + b[i]
public class triplet : IComparable {
public int a, b, c;
// Constructor
public triplet(int a, int b, int c)
{
this.a = a;
this.b = b;
this.c = c;
}
// Sort values according to array
public int CompareTo(triplet o)
{
return this.a - o.a;
}
}
public class GFG {
// Stores the segment tree
static int []seg;
// Function to find the maximum
// possible value according to the
// given condition
public void maxValue(
int []a, int []b, int n, int k)
{
// Initialize triplet array
triplet []arr = new triplet[n];
// Store the values a[i], b[i],
// a[i] + b[i]
for (int i = 0; i < n; i++) {
arr[i] = new triplet(a[i], b[i],
a[i] + b[i]);
}
// Sort the array according
// to array []a
Array.Sort(arr);
// Build segment tree
seg = new int[4 * n];
build(arr, 0, 0, n - 1);
// Intialise the maxvalue of
// the selected pairs
int maxvalue = int.MinValue;
// Traverse the array
for (int i = 0; i < n; i++) {
// For each value find the
// floor(arr[i] + k)
int right = search(arr,
arr[i].a + k);
// Find the maximum value of
// the select pairs i and max
// from (i + 1, right)
if (right != -1) {
maxvalue = Math.Max(
maxvalue, arr[i].b - arr[i].a
+ getMax(arr, 0, 0, n - 1,
i + 1, right));
}
}
// Print the maximum value
Console.WriteLine(maxvalue);
}
// Function to search floor of
// the current value
public int search(
triplet []arr, int val)
{
// Initialise low and high values
int low = 0, high = arr.Length - 1;
int ans = -1;
// Perform Binary Search
while (low <= high) {
int mid = low + (high - low) / 2;
// If the current value is
// <= val then store the
// candidate answer and
// find for rigtmost one
if (arr[mid].a <= val) {
ans = mid;
low = mid + 1;
}
else
high = mid - 1;
}
return ans;
}
// Function to build segment tree
public static void build(
triplet []arr, int index,
int s, int e)
{
// Base Case
if (s == e) {
seg[index] = arr[s].c;
return;
}
int mid = s + (e - s) / 2;
// Build the left and right
// segment trees
build(arr, 2 * index + 1, s, mid);
build(arr, 2 * index + 2, mid + 1, e);
// Update current index
seg[index] = Math.Max(seg[2 * index + 1],
seg[2 * index + 2]);
}
// Function to get maximum value
// in the range [qs, qe]
public static int getMax(
triplet []arr, int index, int s,
int e, int qs, int qe)
{
// If segement is not in range
if (qe < s || e < qs)
return int.MinValue / 2;
// If segement is completely
// inside the query
if (s >= qs && e <= qe)
return seg[index];
// Calcualate the maximum value
// in left and right half
int mid = s + (e - s) / 2;
return Math.Max(
getMax(arr, 2 * index + 1,
s, mid, qs, qe),
getMax(arr, 2 * index + 2,
mid + 1, e, qs, qe));
}
// Driver Code
public static void Main(String []args)
{
int N = 4, K = 1;
int []A = { 5, 6, 9, 10 };
int []B = { 3, 0, 10, -10 };
// Function call
new GFG().maxValue(A, B, N, K);
}
}
// This code is contributed by 29AjayKumar
4
时间复杂度: O(N * log N)
辅助空间: O(N)