📌  相关文章
📜  根据给定条件最大化两个给定数组中的一对值

📅  最后修改于: 2021-09-05 08:38:23             🧑  作者: Mango

给定两个数组A[]B[]N 个整数和一个整数K 组成,任务是找到B[i] + B[j] + abs(A[i] – A[j])的最大值通过选择任何对(i, j)使得abs(A[i] – A[j]) ≤ K

例子:

朴素的方法:最简单的方法是从给定的数组中生成所有可能的对,并对满足给定条件的那些对进行计数。检查所有对后,打印所有对的计数。

时间复杂度: 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])

请按照以下步骤解决问题:

  • 根据数组A[]的值对所有值B[i]B[i] + A[i] 进行排序。
  • maxValue初始化为 INT_MIN 以存储最终最大答案并初始化存储所有值A[i] + B[i]的范围最大查询段树。
  • 遍历数组A[]并执行以下操作:
    • 对于每个元素找到索引,说right ,这样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)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live