确定是否可以通过将杆段分成两半来获得 Array
给定一个长度为L的棒和一个长度为N的数组arr[] ,任务是找出是否有可能将棒分成N-1次分段,使得所有分段的长度都存在于数组中。每次长度为x的段可以分为长度为⌈x/2⌉和x – ⌈x/2⌉的两部分。
例子:
Input: L = 1000, N = 1, arr[] = {1000}
Output: YES
Explanation: It is possible to get the array a by performing (N – 1 = 0) 0 operations on rod.
Input: L = 1104, N = 2, arr[] = {861, 243}
Output NO
Explanation: N – 1 = 1, i.e. perform 1 operation.
After one operation only possible segments will be {552, 552}, which are not present in given array.
Input: L = 6, N = 3, arr[] = {1, 2, 3}
Output: YES
Explanation: number of operations = 3 – 1 = 2.
After one operation only possible array will be {3, 3} .
Now choose first segment (that is 3) and divide it into two parts which are 1 and 2.
After second operation array will be = {1, 2, 3}
( All permutations of {1, 2, 3} are acceptable, because order doesn’t matter )
方法:可以基于以下思想使用堆数据结构来解决问题:
Try to break that segment into two pieces which has the maximum length and not yet found in the array.
请按照下面给出的插图更好地理解:
插图:
Consider L = 6, arr[] = {1, 2, 3}
1st Operation:
=> Break 6 into two segments. Two segments are {3, 3}.
=> One 3 is present in array.
2nd Operation:
=> Break another 3 into two segments. Two segments are {1, 2}.
=> Both 1 and 2 are present in array.
Two operations are finished and all the segment lengths are also present in the array.
按照下面提到的步骤来实现这个想法:
- 将数组的所有元素放在一个最大堆中(比如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)