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

📅  最后修改于: 2021-04-23 06:52:21             🧑  作者: Mango

给定由N个整数和整数K组成的两个数组A []B [] ,任务是找到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 []并执行以下操作:
    • 对于每个元素,找到索引,说正确,使用二进制搜索使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)