Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在2个排序数组(每个数组1个值)中查找值对,其中总和最接近目标值_Java_Arrays_Optimization_Dynamic Programming_Closest - Fatal编程技术网

Java 在2个排序数组(每个数组1个值)中查找值对,其中总和最接近目标值

Java 在2个排序数组(每个数组1个值)中查找值对,其中总和最接近目标值,java,arrays,optimization,dynamic-programming,closest,Java,Arrays,Optimization,Dynamic Programming,Closest,原始问题有一个由2个整数组成的未排序列表。为了简化这个问题,让我们考虑输入是整数2个整数数组和一个整数目标。如果存在多个解决方案对,则可以重复值对 例如:[7,8,14],[5,10,14]目标:20 解是[14,5],因为第一个数组中的14和第二个数组中的5和19最接近于20 我的解决方案是从头到尾循环两个数组,并与跟踪的最小差异进行比较,如果新的差异较小,则进行更新 但这是蛮力。有没有更好的解决办法 我在网上找到的大多数解决方案都是从同一个数组中找到目标,2个数组的目标问题和1个数组之间有什

原始问题有一个由2个整数组成的未排序列表。为了简化这个问题,让我们考虑输入是整数2个整数数组和一个整数目标。如果存在多个解决方案对,则可以重复值对

例如:[7,8,14],[5,10,14]目标:20 解是[14,5],因为第一个数组中的14和第二个数组中的5和19最接近于20

我的解决方案是从头到尾循环两个数组,并与跟踪的最小差异进行比较,如果新的差异较小,则进行更新

但这是蛮力。有没有更好的解决办法


我在网上找到的大多数解决方案都是从同一个数组中找到目标,2个数组的目标问题和1个数组之间有什么相似之处吗?

一个关键洞察:给定一对(x,y)的和高于目标,该和比任何对(x,y')的和都要近,其中y'>y。相反,如果(x,y)的和低于目标,则该和比任何对(x',y)的和更接近,其中x' 这将产生一个线性时间的算法:

  • 开始列表X的第一个元素和列表Y的最后一个元素
  • 检查它是否是目前为止最好的一对(如果是,请记住)
  • 如果该和小于目标,则移动到X的下一个较高元素。如果该和大于目标,则移动到Y的下一个较低元素
  • 循环步骤2-3,直到X或Y中的元素用完为止
  • 在Java中:

    private static Pair<Integer, Integer> findClosestSum(List<Integer> X, List<Integer> Y, int target) {
        double bestDifference = Integer.MAX_VALUE;
        Pair<Integer, Integer> bestPair = null;
        int xIndex = 0;
        int yIndex = Y.size() - 1;
    
        while (true) {
            double sum = X.get(xIndex) + Y.get(yIndex);
            double difference = Math.abs(sum - target);
            if (difference < bestDifference) {
                bestPair = new Pair<>(X.get(xIndex), Y.get(yIndex));
                bestDifference = difference;
            }
    
            if (sum > target) {
                yIndex -= 1;
                if (yIndex < 0) {
                    return bestPair;
                }
            } else if (sum < target) {
                xIndex += 1;
                if (xIndex == X.size()) {
                    return bestPair;
                }
            } else {
                // Perfect match :)
                return bestPair;
            }
        }
    }
    
    私有静态对findClosestSum(列表X、列表Y、int目标){
    double bestDifference=整数最大值;
    Pair-bestPair=null;
    int xIndex=0;
    int yIndex=Y.size()-1;
    while(true){
    双和=X.get(xIndex)+Y.get(yIndex);
    双差=Math.abs(和-目标);
    如果(差异<最佳差异){
    最佳配对=新配对(X.get(xIndex),Y.get(yIndex));
    差异=差异;
    }
    如果(总和>目标){
    yIndex-=1;
    if(yIndex<0){
    返回最佳对;
    }
    }否则如果(总和<目标值){
    xIndex+=1;
    如果(xIndex==X.size()){
    返回最佳对;
    }
    }否则{
    //完美匹配:)
    返回最佳对;
    }
    }
    }
    
    您可以通过开始段落中的逻辑证明此算法是详尽的。对于任何未被访问的对,必须有一对包含被访问的两个元素中的一个,并且其总和严格地接近目标


    编辑:如果您只想要小于目标值的总和(而不是超出目标值的总和),则同样的逻辑仍然适用。在超调情况下,(x,y')与(x,y)一样无效,因此它不可能是更好的候选和。在这种情况下,只需修改步骤2,仅当总和是目前为止最接近的不超过总和时才存储该总和。

    谢谢您的算法,我已经实现了我的逻辑。是的,它需要是目标下最接近的一对,所以我相应地修改了代码。由于输入可以是重复的,因此我确保句柄也是重复的。结果也可以是多个,所以也可以处理。如果您发现任何潜在的优化,请告诉我。代码如下:

      public static List<List<Integer>> findClosest(int[] x, int[] y, int target){
             List<List<Integer>> result = new ArrayList<List<Integer>>();
             int[] pair = new int[2];
             int bestDiff = Integer.MIN_VALUE;
             int xIndex = 0;
             int yIndex = y.length - 1;
             //while left doesn't reach left end and right doesn't reach right end
             while(xIndex < x.length && yIndex >= 0){
                 int xValue = x[xIndex];
                 int yValue = y[yIndex];
                 int diff = xValue + yValue - target;
                 //values greater than target, y pointer go right
                 if(diff > 0){
                     yIndex--;
                     while(yIndex > 0 && yValue == y[yIndex - 1]) yIndex--;
                 }else{//combined == 0 which match target and < 0 which means the sum is less than target
                     //duplicates result, just add
                     if(diff == bestDiff){
                         result.add(Arrays.asList(xValue, yValue));
                     }
                     //found better pair, clear array and add new pair
                     else if(diff > bestDiff){
                         result.clear();
                         result.add(Arrays.asList(xValue, yValue));
                         bestDiff = diff;
                     }
                     xIndex++;
                 }
             }
             return result;
      }
    
    公共静态列表findClosest(int[]x,int[]y,int目标){
    列表结果=新建ArrayList();
    int[]对=新的int[2];
    int bestDiff=整数.MIN_值;
    int xIndex=0;
    int yIndex=y.长度-1;
    //而左不到左端,右不到右端
    而(xIndex=0){
    int xValue=x[xIndex];
    int yValue=y[yIndex];
    int diff=xValue+yValue-目标;
    //值大于目标值,y指针向右移动
    如果(差异>0){
    yIndex--;
    而(yIndex>0&&yValue==y[yIndex-1])yIndex--;
    }否则{//combined==0,与目标匹配,<0,表示总和小于目标
    //重复结果,只需添加
    if(diff==bestDiff){
    add(Arrays.asList(xValue,yValue));
    }
    //找到更好的对,清除数组并添加新对
    否则如果(差异>最佳差异){
    result.clear();
    add(Arrays.asList(xValue,yValue));
    bestDiff=diff;
    }
    xIndex++;
    }
    }
    返回结果;
    }
    
    它是否需要最接近目标而不超过目标,还是允许它超过目标?p、 这听起来像是背包问题的一个变种