📌  相关文章
📜  在未排序的数组中找到 k 个最接近的数字

📅  最后修改于: 2021-10-28 02:02:22             🧑  作者: Mango

给定一个未排序的数组和两个数字 x 和 k,找到与 x 最接近的 k 个值。
例子:

Input : arr[] = {10, 2, 14, 4, 7, 6}, x = 5, k = 3 
Output : 4 6 7
Three closest values of x are 4, 6 and 7.

Input : arr[] = {-10, -50, 20, 17, 80}, x = 20, k = 2
Output : 17, 20

一个简单的解决方案是对数组进行排序。然后将讨论的方法应用于排序数组中的 k 个最接近的值。
时间复杂度: O(n Log n)
更好的解决方案是使用堆数据结构
1) 用前 k 个元素制作最大的差异堆。
2) 对于从 (k+1)-th 元素开始的每个元素,执行以下操作。
…..a) 找出当前元素与 x 的差异。
…..b) 如果差异大于堆的根,则忽略当前元素。
…..c) 否则在移除根后将当前元素插入到堆中。
3) 最后堆有 k 个最接近的元素。

C++
// C++ program to find k closest elements
#include 
using namespace std;
 
void printKclosest(int arr[], int n, int x,
                   int k)
{
    // Make a max heap of difference with
    // first k elements.
    priority_queue > pq;
    for (int i = 0; i < k; i++)
        pq.push({ abs(arr[i] - x), i });
 
    // Now process remaining elements.
    for (int i = k; i < n; i++) {
 
        int diff = abs(arr[i] - x);
 
        // If difference with current
        // element is more than root,
        // then ignore it.
        if (diff > pq.top().first)
            continue;
 
        // Else remove root and insert
        pq.pop();
        pq.push({ diff, i });
    }
 
    // Print contents of heap.
    while (pq.empty() == false) {
        cout << arr[pq.top().second] << " ";
        pq.pop();
    }
}
 
// Driver program to test above functions
int main()
{
    int arr[] = { -10, -50, 20, 17, 80 };
    int x = 20, k = 2;
    int n = sizeof(arr) / sizeof(arr[0]);
    printKclosest(arr, n, x, k);
    return 0;
}


Java
//Java program to find k closest elements
import java.util.Comparator;
import java.util.PriorityQueue;
 
class Pair
{
    Integer key;
    Integer value;
     
    public Pair(Integer key, Integer value)
    {
        this.key = key;
        this.value = value;
    }
    public Integer getKey()
    {
        return key;
    }
    public void setKey(Integer key)
    {
        this.key = key;
    }
    public Integer getValue()
    {
        return value;
    }
    public void setValue(Integer value)
    {
        this.value = value;
    }
}
 
class GFG{
     
public static void printKclosest(int[] arr, int n,
                                 int x, int k)
{
 
    // Make a max heap.
    PriorityQueue pq = new PriorityQueue<>(
                             new Comparator()
    {
        public int compare(Pair p1, Pair p2)
        {
            return p2.getValue().compareTo(
                   p1.getValue());
        }
    });
     
    // Build heap of difference with
    // first k elements
    for(int i = 0; i < k; i++)
    {
        pq.offer(new Pair(arr[i],
                 Math.abs(arr[i] - x)));
    }
     
    // Now process remaining elements.
    for(int i = k; i < n; i++)
    {
        int diff = Math.abs(arr[i] - x);
         
        // If difference with current
        // element is more than root,
        // then ignore it.
        if(diff > pq.peek().getValue()) continue;
         
        // Else remove root and insert
        pq.poll();
        pq.offer(new Pair(arr[i], diff));
    }
     
    // Print contents of heap.
    while(!pq.isEmpty())
    {
        System.out.print(pq.poll().getKey() + " ");
    }
}
 
// Driver code
public static void main(String[] args)
{
    int arr[] = { -10, -50, 20, 17, 80 };
    int x = 20, k = 2;
    int n = arr.length;
     
    printKclosest(arr, n, x, k);
}
}
 
// This code is contributed by Ashok Borra


Python3
# Python3 program to find k closest elements
import math
import sys
from queue import PriorityQueue
def printKclosest(arr,n,x,k):
 
    # Make a max heap of difference with
    # first k elements.
    pq = PriorityQueue()
    for i in range(k):
        pq.put((-abs(arr[i]-x),i))
 
    # Now process remaining elements
    for i in range(k,n):
        diff = abs(arr[i]-x)
        p,pi = pq.get()
        curr = -p
 
        # If difference with current
        # element is more than root,
        # then put it back.
        if diff>curr:
            pq.put((-curr,pi))
            continue
        else:
 
            # Else remove root and insert
            pq.put((-diff,i))
             
    # Print contents of heap.
    while(not pq.empty()):
        p,q = pq.get()
        print("{} ".format(arr[q]),end = "")
 
# Driver program to test above functions
if __name__=='__main__':
    arr = [-10,-50,20,17,80]
    x,k = 20,2
    n = len(arr)
    printKclosest(arr, n, x, k)
 
# This code is contributed by Vikash Kumar 37


C#
// C# program to find k closest elements
using System;
using System.Collections.Generic;
class GFG {
 
  static void printKclosest(int[] arr, int n, int x, int k)
  {
    // Make a max heap of difference with
    // first k elements.
    List> pq = new List>();
    for (int i = 0; i < k; i++)
    {
      pq.Add(new Tuple(Math.Abs(arr[i] - x), i));
    }
 
    pq.Sort();
    pq.Reverse();
 
    // Now process remaining elements.
    for (int i = k; i < n; i++)
    {
 
      int diff = Math.Abs(arr[i] - x);
 
      // If difference with current
      // element is more than root,
      // then ignore it.
      if (diff > pq[0].Item1)
        continue;
 
      // Else remove root and insert
      pq.RemoveAt(0);
      pq.Add(new Tuple(diff, i));
      pq.Sort();
      pq.Reverse();
    }
 
    // Print contents of heap.
    while (pq.Count > 0)
    {
      Console.Write(arr[pq[0].Item2] + " ");
      pq.RemoveAt(0);
    }
  }
 
  // Driver code
  static void Main()
  {
    int[] arr = { -10, -50, 20, 17, 80 };
    int x = 20, k = 2;
    int n = arr.Length;
    printKclosest(arr, n, x, k);
  }
}
 
// This code is contributed by divyesh072019.


输出:
17 20

时间复杂度: O(n Log k)

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