📌  相关文章
📜  在两个数组中找到具有最小和的k对|套装2

📅  最后修改于: 2021-05-04 15:55:49             🧑  作者: Mango

给定两个数组arr1 []和arr2 []以升序排序,并且整数K。任务是找到具有最小总和的k对,以使对中的一个元素属于arr1 [],另一个元素属于arr2 [] 。数组的大小可能不同。假设所有元素在每个数组中都是不同的。
例子:

Input: a1[] = {1, 7, 11}
       a2[] = {2, 4, 6}
       k = 3
Output: [1, 2], [1, 4], [1, 6]
The first 3 pairs are returned 
from the sequence [1, 2], [1, 4], [1, 6], [7, 2],
[7, 4], [11, 2], [7, 6], [11, 4], [11, 6].

Input: a1[] = { 2, 3, 4 }
       a2[] = { 1, 6, 5, 8 }  
       k = 4
Output: [1, 2] [1, 3] [1, 4] [2, 6] 



这里讨论了一种具有时间复杂度O(k * n1)的方法。
高效的方法:由于数组已经排序。可以使用下面给出的算法来解决此问题:

  • 这个想法是要维护两个指针,一个指针指向(a1,a2)中的一对,另一个指向(a2,a1)中的另一个。每次比较两个对所指向的元素之和,并打印最小的对。此后,将指针增加到打印对中大于另一个的元素的指针。这有助于获得下一个可能的k个最小的对。
  • 一旦指针已更新到该元素,使其开始再次指向数组的第一个元素,则将另一个指针更新为下一个值。此更新是周期性进行的。
  • 另外,当两对都指向同一元素时,请更新两对中的指针,以避免打印多余的对。根据rule1更新一对指针,而与rule1相反的另一对则更新。这样做是为了确保考虑所有排列,并且没有重复的对。

下面是算法的工作示例1:

以下是上述方法的C++实现:

C++
// C++ program to print the k smallest
// pairs | Set 2
#include 
using namespace std;
 
typedef struct _pair {
    int first, second;
} _pair;
 
// Function to print the K smallest pairs
void printKPairs(int a1[], int a2[],
                 int size1, int size2, int k)
{
 
    // if k is greater than total pairs
    if (k > (size2 * size1)) {
        cout << "k pairs don't exist\n";
        return;
    }
 
    // _pair _one keeps track of
    // 'first' in a1 and 'second' in a2
    // in _two, _two.first keeps track of
    // element in the a2[] and _two.second in a1[]
    _pair _one, _two;
    _one.first = _one.second = _two.first = _two.second = 0;
 
    int cnt = 0;
 
    // Repeat the above process till
    // all K pairs are printed
    while (cnt < k) {
 
        // when both the pointers are pointing
        // to the same elements (point 3)
        if (_one.first == _two.second
            && _two.first == _one.second) {
            if (a1[_one.first] < a2[_one.second]) {
                cout << "[" << a1[_one.first]
                     << ", " << a2[_one.second] << "] ";
 
                // updates according to step 1
                _one.second = (_one.second + 1) % size2;
                if (_one.second == 0) // see point 2
                    _one.first = (_one.first + 1) % size1;
 
                // updates opposite to step 1
                _two.second = (_two.second + 1) % size2;
                if (_two.second == 0)
                    _two.first = (_two.first + 1) % size2;
            }
            else {
                cout << "[" << a2[_one.second]
                     << ", " << a1[_one.first] << "] ";
 
                // updates according to rule 1
                _one.first = (_one.first + 1) % size1;
                if (_one.first == 0) // see point 2
                    _one.second = (_one.second + 1) % size2;
 
                // updates opposite to rule 1
                _two.first = (_two.first + 1) % size2;
                if (_two.first == 0) // see point 2
                    _two.second = (_two.second + 1) % size1;
            }
        }
        // else update as necessary (point 1)
        else if (a1[_one.first] + a2[_one.second]
                 <= a2[_two.first] + a1[_two.second]) {
            if (a1[_one.first] < a2[_one.second]) {
                cout << "[" << a1[_one.first] << ", "
                     << a2[_one.second] << "] ";
 
                // updating according to rule 1
                _one.second = ((_one.second + 1) % size2);
                if (_one.second == 0) // see point 2
                    _one.first = (_one.first + 1) % size1;
            }
            else {
                cout << "[" << a2[_one.second] << ", "
                     << a1[_one.first] << "] ";
 
                // updating according to rule 1
                _one.first = ((_one.first + 1) % size1);
                if (_one.first == 0) // see point 2
                    _one.second = (_one.second + 1) % size2;
            }
        }
        else if (a1[_one.first] + a2[_one.second]
                 > a2[_two.first] + a1[_two.second]) {
            if (a2[_two.first] < a1[_two.second]) {
                cout << "[" << a2[_two.first] << ", " << a1[_two.second] << "] ";
 
                // updating according to rule 1
                _two.first = ((_two.first + 1) % size2);
                if (_two.first == 0) // see point 2
                    _two.second = (_two.second + 1) % size1;
            }
            else {
                cout << "[" << a1[_two.second]
                     << ", " << a2[_two.first] << "] ";
 
                // updating according to rule 1
                _two.second = ((_two.second + 1) % size1);
                if (_two.second == 0) // see point 2
                    _two.first = (_two.first + 1) % size1;
            }
        }
        cnt++;
    }
}
 
// Driver Code
int main()
{
 
    int a1[] = { 2, 3, 4 };
    int a2[] = { 1, 6, 5, 8 };
    int size1 = sizeof(a1) / sizeof(a1[0]);
    int size2 = sizeof(a2) / sizeof(a2[0]);
    int k = 4;
    printKPairs(a1, a2, size1, size2, k);
    return 0;
}


Java
// Java program to print
// the k smallest pairs
// | Set 2
import java.util.*;
class GFG{
 
static class _pair
{
  int first, second;
};
 
// Function to print the K
// smallest pairs
static void printKPairs(int a1[], int a2[],
                        int size1, int size2,
                        int k)
{
  // if k is greater than
  // total pairs
  if (k > (size2 * size1))
  {
    System.out.print("k pairs don't exist\n");
    return;
  }
 
  // _pair _one keeps track of
  // 'first' in a1 and 'second' in a2
  // in _two, _two.first keeps track of
  // element in the a2[] and _two.second
  // in a1[]
  _pair _one = new _pair();
  _pair  _two = new _pair();
  _one.first = _one.second =
  _two.first = _two.second = 0;
 
  int cnt = 0;
 
  // Repeat the above process
  // till all K pairs are printed
  while (cnt < k)
  {
    // when both the pointers are
    // pointing to the same elements
    // (point 3)
    if (_one.first == _two.second &&
        _two.first == _one.second)
    {
      if (a1[_one.first] <
          a2[_one.second])
      {
        System.out.print("[" +  a1[_one.first] +
                         ", " +  a2[_one.second] +
                         "] ");
 
        // updates according to step 1
        _one.second = (_one.second + 1) %
                       size2;
         
        // see point 2
        if (_one.second == 0)
          _one.first = (_one.first + 1) %
                        size1;
 
        // updates opposite to step 1
        _two.second = (_two.second + 1) %
                       size2;
         
        if (_two.second == 0)
          _two.first = (_two.first + 1) %
                        size2;
      }
      else
      {
        System.out.print("[" +  a2[_one.second] +
                         ", " +  a1[_one.first] +
                         "] ");
 
        // updates according to rule 1
        _one.first = (_one.first + 1) %
                      size1;
         
        // see point 2
        if (_one.first == 0)
          _one.second = (_one.second + 1) %
                         size2;
 
        // updates opposite to rule 1
        _two.first = (_two.first + 1) %
                      size2;
         
        // see point 2
        if (_two.first == 0)
           
          _two.second = (_two.second + 1) %
                         size1;
      }
    }
     
    // else update as
    // necessary (point 1)
    else if (a1[_one.first] +
             a2[_one.second] <=
             a2[_two.first] +
             a1[_two.second])
    {
      if (a1[_one.first] <
          a2[_one.second])
      {
        System.out.print("[" +  a1[_one.first] +
                         ", " + a2[_one.second] +
                         "] ");
 
        // updating according to rule 1
        _one.second = ((_one.second + 1) %
                        size2);
         
        // see point 2
        if (_one.second == 0)
          _one.first = (_one.first + 1) %
                        size1;
      }
      else
      {
        System.out.print("[" +  a2[_one.second] +
                         ", " + a1[_one.first] +
                         "] ");
 
        // updating according to rule 1
        _one.first = ((_one.first + 1) %
                       size1);
         
        // see point 2
        if (_one.first == 0)
          _one.second = (_one.second + 1) %
                         size2;
      }
    }
    else if (a1[_one.first] +
             a2[_one.second] >
             a2[_two.first] +
             a1[_two.second])
    {
      if (a2[_two.first] <
          a1[_two.second])
      {
        System.out.print("[" +  a2[_two.first] +
                         ", " +  a1[_two.second] +
                         "] ");
 
        // updating according to rule 1
        _two.first = ((_two.first + 1) %
                       size2);
         
        // see point 2
        if (_two.first == 0)
          _two.second = (_two.second + 1) %
                         size1;
      }
      else {
        System.out.print("[" +  a1[_two.second] +
                         ", " +  a2[_two.first] +
                         "] ");
 
        // updating according to rule 1
        _two.second = ((_two.second + 1) %
                        size1);
         
        // see point 2
        if (_two.second == 0)
          _two.first = (_two.first + 1) %
                        size1;
      }
    }
    cnt++;
  }
}
 
// Driver Code
public static void main(String[] args)
{
  int a1[] = {2, 3, 4};
  int a2[] = {1, 6, 5, 8};
  int size1 = a1.length;
  int size2 = a2.length;
  int k = 4;
  printKPairs(a1, a2,
              size1, size2, k);
}
}
 
// This code is contributed by gauravrajput1


Python3
# Python3 program to print the k smallest
# pairs | Set 2
 
# Function to print the K smallest pairs
def printKPairs(a1, a,size1, size2, k):
 
    # if k is greater than total pairs
    if (k > (size2 * size1)):
        print("k pairs don't exist\n")
        return
 
    # _pair _one keeps track of
    # 'first' in a1 and 'second' in a2
    # in _two, _two[0] keeps track of
    # element in the a2and _two[1] in a1[]
    _one, _two = [0, 0], [0, 0]
 
    cnt = 0
 
    # Repeat the above process till
    # all K pairs are printed
    while (cnt < k):
 
        # when both the pointers are pointing
        # to the same elements (po3)
        if (_one[0] == _two[1]
            and _two[0] == _one[1]):
            if (a1[_one[0]] < a2[_one[1]]):
                print("[", a1[_one[0]], ", ",
                        a2[_one[1]],"] ", end=" ")
 
                # updates according to step 1
                _one[1] = (_one[1] + 1) % size2
                if (_one[1] == 0): #see po2
                    _one[0] = (_one[0] + 1) % size1
 
                # updates opposite to step 1
                _two[1] = (_two[1] + 1) % size2
                if (_two[1] == 0):
                    _two[0] = (_two[0] + 1) % size2
 
            else:
                print("[",a2[_one[1]]
                    ,", ",a1[_one[0]],"] ",end=" ")
 
                # updates according to rule 1
                _one[0] = (_one[0] + 1) % size1
                if (_one[0] == 0): #see po2
                    _one[1] = (_one[1] + 1) % size2
 
                # updates opposite to rule 1
                _two[0] = (_two[0] + 1) % size2
                if (_two[0] == 0): #see po2
                    _two[1] = (_two[1] + 1) % size1
 
        # else update as necessary (po1)
        elif (a1[_one[0]] + a2[_one[1]]
                <= a2[_two[0]] + a1[_two[1]]):
            if (a1[_one[0]] < a2[_one[1]]):
                print("[",a1[_one[0]],", ",
                    a2[_one[1]],"] ",end=" ")
 
                # updating according to rule 1
                _one[1] = ((_one[1] + 1) % size2)
                if (_one[1] == 0): # see po2
                    _one[0] = (_one[0] + 1) % size1
            else:
                print("[",a2[_one[1]],", ",
                    a1[_one[0]],"] ", end=" ")
 
                # updating according to rule 1
                _one[0] = ((_one[0] + 1) % size1)
                if (_one[0] == 0): # see po2
                    _one[1] = (_one[1] + 1) % size2
 
        elif (a1[_one[0]] + a2[_one[1]]
                > a2[_two[0]] + a1[_two[1]]):
            if (a2[_two[0]] < a1[_two[1]]):
                print("[",a2[_two[0]],", ",a1[_two[1]],"] ",end=" ")
 
                # updating according to rule 1
                _two[0] = ((_two[0] + 1) % size2)
                if (_two[0] == 0): #see po2
                    _two[1] = (_two[1] + 1) % size1
 
            else:
                print("[",a1[_two[1]]
                    ,", ",a2[_two[0]],"] ",end=" ")
 
                # updating according to rule 1
                _two[1] = ((_two[1] + 1) % size1)
                if (_two[1] == 0): #see po2
                    _two[0] = (_two[0] + 1) % size1
 
        cnt += 1
 
# Driver Code
if __name__ == '__main__':
 
    a1= [2, 3, 4]
    a2= [1, 6, 5, 8]
    size1 = len(a1)
    size2 = len(a2)
    k = 4
    printKPairs(a1, a2, size1, size2, k)
 
# This code is contributed by mohit kumar 29


C#
// C# program to print
// the k smallest pairs
// | Set 2
using System;
class GFG{
 
public class _pair
{
  public int first,
             second;
};
 
// Function to print the K
// smallest pairs
static void printKPairs(int []a1, int []a2,
                        int size1, int size2,
                        int k)
{
  // if k is greater than
  // total pairs
  if (k > (size2 * size1))
  {
    Console.Write("k pairs don't exist\n");
    return;
  }
 
  // _pair _one keeps track of
  // 'first' in a1 and 'second' in a2
  // in _two, _two.first keeps track of
  // element in the a2[] and _two.second
  // in a1[]
  _pair _one = new _pair();
  _pair  _two = new _pair();
  _one.first = _one.second =
  _two.first = _two.second = 0;
 
  int cnt = 0;
 
  // Repeat the above process
  // till all K pairs are printed
  while (cnt < k)
  {
    // when both the pointers are
    // pointing to the same elements
    // (point 3)
    if (_one.first == _two.second &&
        _two.first == _one.second)
    {
      if (a1[_one.first] <
          a2[_one.second])
      {
        Console.Write("[" +  a1[_one.first] +
                      ", " +  a2[_one.second] +
                      "] ");
 
        // updates according to step 1
        _one.second = (_one.second + 1) %
                        size2;
 
        // see point 2
        if (_one.second == 0)
          _one.first = (_one.first + 1) %
                         size1;
 
        // updates opposite to step 1
        _two.second = (_two.second + 1) %
                        size2;
 
        if (_two.second == 0)
          _two.first = (_two.first + 1) %
                         size2;
      }
      else
      {
        Console.Write("[" + a2[_one.second] +
                      ", " + a1[_one.first] +
                      "] ");
 
        // updates according to rule 1
        _one.first = (_one.first + 1) %
                       size1;
 
        // see point 2
        if (_one.first == 0)
          _one.second = (_one.second + 1) %
                          size2;
 
        // updates opposite to rule 1
        _two.first = (_two.first + 1) %
                       size2;
 
        // see point 2
        if (_two.first == 0)
          _two.second = (_two.second + 1) %
                          size1;
      }
    }
 
    // else update as
    // necessary (point 1)
    else if (a1[_one.first] +
             a2[_one.second] <=
             a2[_two.first] +
             a1[_two.second])
    {
      if (a1[_one.first] <
          a2[_one.second])
      {
        Console.Write("[" + a1[_one.first] +
                      ", " + a2[_one.second] +
                      "] ");
 
        // updating according to rule 1
        _one.second = ((_one.second + 1) %
                         size2);
         
        // see point 2
        if (_one.second == 0)
          _one.first = (_one.first + 1) %
                         size1;
      }
      else
      {
        Console.Write("[" + a2[_one.second] +
                      ", " + a1[_one.first] +
                      "] ");
 
        // updating according to rule 1
        _one.first = ((_one.first + 1) %
                        size1);
 
        // see point 2
        if (_one.first == 0)
          _one.second = (_one.second + 1) %
                          size2;
      }
    }
    else if (a1[_one.first] +
             a2[_one.second] >
             a2[_two.first] +
             a1[_two.second])
    {
      if (a2[_two.first] <
          a1[_two.second])
      {
        Console.Write("[" + a2[_two.first] +
                      ", " + a1[_two.second] +
                      "] ");
 
        // updating according to rule 1
        _two.first = ((_two.first + 1) %
                        size2);
 
        // see point 2
        if (_two.first == 0)
          _two.second = (_two.second + 1) %
                          size1;
      }
      else {
        Console.Write("[" + a1[_two.second] +
                      ", " + a2[_two.first] +
                      "] ");
 
        // updating according to rule 1
        _two.second = ((_two.second + 1) %
                         size1);
 
        // see point 2
        if (_two.second == 0)
          _two.first = (_two.first + 1) %
                         size1;
      }
    }
    cnt++;
  }
}
 
// Driver Code
public static void Main(String[] args)
{
  int []a1 = {2, 3, 4};
  int []a2 = {1, 6, 5, 8};
  int size1 = a1.Length;
  int size2 = a2.Length;
  int k = 4;
  printKPairs(a1, a2,
              size1,
              size2, k);
}
}
 
// This code is contributed by gauravrajput1


输出:
[1, 2] [1, 3] [1, 4] [2, 6]







时间复杂度:O(K)