给定一个由正整数组成的数组arr[] ,任务是计算对(arr[i], arr[j])的最大可能数量,使得arr[i] + arr[j]是2的幂。
注意:一个元素最多可以使用一次以形成一对。
例子:
Input: arr[] = {3, 11, 14, 5, 13}
Output: 2
All valid pairs are (13, 3) and (11, 5) both sum up to 16 which is a power of 2.
We could have used (3, 5) but by doing so maximum of 1 pair could only be formed.
Therefore, (3, 5) is not optimal.
Input: arr[] = {1, 2, 3}
Output: 1
1 and 3 can be paired to form 4, which is a power of 2.
一个简单的解决方案是考虑每一对并检查这对的总和是否是 2 的幂。此解决方案的时间复杂度为 O(n * n)
一种有效的方法:是从数组中找到最大的元素,比如X,然后从数组的其余元素Y 中找到最大的元素,使得Y ≤ X并且X + Y是2的幂。这是对的最佳选择,因为即使Y与其他元素(例如Z)形成有效对,那么Z将与Y以外的元素配对(如果可能)以最大化有效对的数量。
C++
// C++ implementation of above approach
#include
using namespace std;
// Function to return the count of valid pairs
int countPairs(int a[], int n)
{
// Storing occurrences of each element
unordered_map mp;
for (int i = 0; i < n; i++)
mp[a[i]]++;
// Sort the array in deceasing order
sort(a, a + n, greater());
// Start taking largest element each time
int count = 0;
for (int i = 0; i < n; i++) {
// If element has already been paired
if (mp[a[i]] < 1)
continue;
// Find the number which is greater than
// a[i] and power of two
int cur = 1;
while (cur <= a[i])
cur <<= 1;
// If there is a number which adds up with a[i]
// to form a power of two
if (mp[cur - a[i]]) {
// Edge case when a[i] and crr - a[i] is same
// and we have only one occurrence of a[i] then
// it cannot be paired
if (cur - a[i] == a[i] and mp[a[i]] == 1)
continue;
count++;
// Remove already paired elements
mp[cur - a[i]]--;
mp[a[i]]--;
}
}
// Return the count
return count;
}
// Driver code
int main()
{
int a[] = { 3, 11, 14, 5, 13 };
int n = sizeof(a) / sizeof(a[0]);
cout << countPairs(a, n);
return 0;
}
Java
// Java implementation of above approach
import java.util.TreeMap;
class Count
{
// Function to return the count of valid pairs
static int countPairs(int[] a, int n)
{
// To keep the element in sorted order
TreeMap map = new TreeMap<>();
for (int i = 0; i < n; i++)
{
map.put(a[i], 1);
}
// Start taking largest element each time
int count = 0;
for (int i = 0; i < n; i++)
{
// If element has already been paired
if (map.get(a[i]) < 1)
continue;
// Find the number which is greater than
// a[i] and power of two
int cur = 1;
while (cur <= a[i])
cur <<= 1;
// If there is a number which adds up with a[i]
// to form a power of two
if (map.containsKey(cur - a[i]))
{
// Edge case when a[i] and crr - a[i] is same
// and we have only one occurrence of a[i] then
// it cannot be paired
if (cur - a[i] == a[i] && map.get(a[i]) == 1)
continue;
count++;
// Remove already paired elements
map.put(cur - a[i], map.get(cur - a[i]) - 1);
map.put(a[i], map.get(a[i]) - 1);
}
}
// Return the count
return count;
}
// Driver code
public static void main(String[] args)
{
int[] a = { 3, 11, 14, 5, 13 };
int n = a.length;
System.out.println(countPairs(a, n));
}
}
// This code is contributed by Vivekkumar Singh
Python3
# Python3 implementation of above approach
# Function to return the count
# of valid pairs
def countPairs(a, n) :
# Storing occurrences of each element
mp = dict.fromkeys(a, 0)
for i in range(n) :
mp[a[i]] += 1
# Sort the array in deceasing order
a.sort(reverse = True)
# Start taking largest element
# each time
count = 0
for i in range(n) :
# If element has already been paired
if (mp[a[i]] < 1) :
continue
# Find the number which is greater
# than a[i] and power of two
cur = 1
while (cur <= a[i]) :
cur = cur << 1
# If there is a number which adds
# up with a[i] to form a power of two
if (cur - a[i] in mp.keys()) :
# Edge case when a[i] and crr - a[i]
# is same and we have only one occurrence
# of a[i] then it cannot be paired
if (cur - a[i] == a[i] and mp[a[i]] == 1) :
continue
count += 1
# Remove already paired elements
mp[cur - a[i]] -= 1
mp[a[i]] -= 1
# Return the count
return count
# Driver code
if __name__ == "__main__" :
a = [ 3, 11, 14, 5, 13 ]
n = len(a)
print(countPairs(a, n))
# This code is contributed by Ryuga
C#
// C# implementation of above approach
using System;
using System.Collections.Generic;
class GFG
{
// Function to return the count of valid pairs
static int countPairs(int[] a, int n)
{
// To keep the element in sorted order
Dictionary map = new Dictionary();
for (int i = 0; i < n; i++)
{
if(!map.ContainsKey(a[i]))
map.Add(a[i], 1);
}
// Start taking largest element each time
int count = 0;
for (int i = 0; i < n; i++)
{
// If element has already been paired
if (map[a[i]] < 1)
continue;
// Find the number which is greater than
// a[i] and power of two
int cur = 1;
while (cur <= a[i])
cur <<= 1;
// If there is a number which adds up
// with a[i] to form a power of two
if (map.ContainsKey(cur - a[i]))
{
// Edge case when a[i] and crr - a[i]
// is same and we have only one occurrence
// of a[i] then it cannot be paired
if (cur - a[i] == a[i] && map[a[i]] == 1)
continue;
count++;
// Remove already paired elements
map[cur - a[i]] = map[cur - a[i]] - 1;
map[a[i]] = map[a[i]] - 1;
}
}
// Return the count
return count;
}
// Driver code
public static void Main(String[] args)
{
int[] a = { 3, 11, 14, 5, 13 };
int n = a.Length;
Console.WriteLine(countPairs(a, n));
}
}
// This code is contributed by Princi Singh
Javascript
C
// Find the number which is greater than
// a[i] and power of two
int cur = 1;
while (cur <= a[i])
cur <<= 1;
2
请注意,上面代码中的以下操作可以使用大于或等于 n 的 2 的最小幂中讨论的最后一种方法在 O(1) 时间内完成
C
// Find the number which is greater than
// a[i] and power of two
int cur = 1;
while (cur <= a[i])
cur <<= 1;
优化上述表达式后,该解的时间复杂度变为 O(n Log n)