📜  确定是否可以通过将杆段分成两半来获得 Array

📅  最后修改于: 2022-05-13 01:57:49.793000             🧑  作者: Mango

确定是否可以通过将杆段分成两半来获得 Array

给定一个长度为L的棒和一个长度为N的数组arr[] ,任务是找出是否有可能将棒分成N-1次分段,使得所有分段的长度都存在于数组中。每次长度为x的段可以分为长度为⌈x/2⌉x – ⌈x/2⌉的两部分。

例子:

方法:可以基于以下思想使用堆数据结构来解决问题:

请按照下面给出的插图更好地理解:

插图:

按照下面提到的步骤来实现这个想法:

  • 将数组的所有元素放在一个最大堆中(比如pqarr )。
  • 同样,维护一个优先级队列(比如说pq )来存储切割棒后获得的段并将 L 放入堆中。
  • 从长度L开始划分。在任何情况下,考虑最大的部分都会很方便。
  • 虽然最大堆 (pq) 不为空:
    • 如果pq的最大元素小于pqarr的最大元素,那么答案是不可能的,因为永远无法获得pqarr的值。
    • 如果pq的最大元素等于pqarr的最大元素,则将其从两个最大堆中删除。
    • 如果pq的最大元素大于pqarr的最大元素,则将其从pq中删除并将其分成两部分。然后将这两个部分再次插入pq中。
  • 迭代结束后,如果堆为空,则返回这是可能的。

下面是上述方法的实现:

C++
// C++ implementation of above appraoch
#include 
using namespace std;
 
// Function to check if it is
// possible to arrange the array
bool solution(int len, int n, vector& arr)
{
 
  // To store elements of array
  // in priorityqueue
  priority_queue pqarr;
 
  // To store segments after each
  // operation in priorityqueue
  priority_queue pq;
 
  for (auto i : arr) {
    pqarr.push(i);
  }
  pq.push(len);
 
  while (pq.size() > 0) {
    int elem = pqarr.top();
    int cur = pq.top();
    pq.pop();
    if (elem > cur) {
      return false;
    }
    if (elem == cur) {
      pqarr.top();
      pqarr.pop();
    }
    else {
      pq.push(cur / 2);
      pq.push((cur + 1) / 2);
    }
  }
  return true;
}
 
// Driver code
int main()
{
  int L = 6;
  int N = 3;
  vector arr = { 2, 1, 3 };
 
  // Function call
  bool flag = solution(L, N, arr);
  if (flag)
    cout << ("YES");
  else
    cout << ("NO");
 
  return 0;
}
 
// This code is contributed by rakeshsahni


Java
// Java implementation of above appraoch
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function to check if it is
    // possible to arrange the array
    public static boolean solution(int len, int n,
                                   int[] arr)
    {
 
        // To store elements of array
        // in priorityqueue
        PriorityQueue pqarr = new PriorityQueue<>(Collections.reverseOrder());
 
        // To store segments after each
        // operation in priorityqueue
        PriorityQueue pq = new PriorityQueue<>(Collections.reverseOrder());
 
        for (int i : arr) {
            pqarr.add(i);
        }
        pq.add(len);
 
        while (pq.size() > 0) {
            int elem = pqarr.peek();
            int cur = pq.poll();
            if (elem > cur) {
                return false;
            }
            if (elem == cur) {
                pqarr.poll();
            }
            else {
                pq.add(cur / 2);
                pq.add((cur + 1) / 2);
            }
        }
        return true;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int L = 6;
        int N = 3;
        int[] arr = { 2, 1, 3 };
 
        // Function call
        boolean flag = solution(L, N, arr);
        if (flag)
            System.out.println("YES");
        else
            System.out.println("NO");
    }
}


输出
YES

时间复杂度: O(N * logN)
辅助空间: O(N)