📜  在两个数组中查找和最小的 k 对 | 2套

📅  最后修改于: 2021-10-26 02:38:05             🧑  作者: 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 最小对。
  • 一旦指针更新到元素,使其再次开始指向数组的第一个元素,将另一个指针更新为下一个值。此更新是循环进行的。
  • 此外,当两个对都指向同一个元素时,更新两个对中的指针以避免额外的对打印。根据规则 1 更新一对的指针,另一对与规则 1 的相反。这样做是为了确保考虑所有排列并且不存在对的重复。

以下是示例 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


Javascript


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

时间复杂度:O(K)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程