给定一个整数数组和一个数字 k,编写一个函数,如果给定的数组可以分成对,使得每对的和都可以被 k 整除,则该函数返回 true。
例子:
Input: arr[] = {9, 7, 5, 3},
k = 6
Output: True
We can divide the array into (9, 3) and
(7, 5). Sum of both of these pairs
is a multiple of 6.
Input: arr[] = {92, 75, 65, 48, 45, 35},
k = 10
Output: True
We can divide the array into (92, 48), (75, 65).
and (45, 35). The sum of all these pairs is a
multiple of 10.
Input: arr[] = {91, 74, 66, 48}, k = 10
Output: False
一个简单的解决方案是遍历每个元素 arr[i]。查找是否还有另一个尚未访问的元素具有像(k – arr[i]%k)这样的余数。如果没有这样的元素,则返回 false。如果找到一对,则将两个元素都标记为已访问。此解决方案的时间复杂度为 O(n 2) ,并且需要 O(n) 额外空间。
一个有效的解决方案是使用哈希。
1) If length of given array is odd, return false.
An odd length array cannot be divided into pairs.
2) Traverse input array and count occurrences of
all remainders (use (arr[i] % k)+k)%k for handling the case of negative integers as well).
freq[((arr[i] % k)+k)%k]++
3) Traverse input array again.
a) Find the remainder of the current element.
b) If remainder divides k into two halves, then
there must be even occurrences of it as it
forms pair with itself only.
c) If the remainder is 0, then there must be
even occurrences.
c) Else, number of occurrences of current
the remainder must be equal to a number of
occurrences of "k - current remainder".
一种有效的方法是使用散列(C++ 中的 unordered_map 和Java的HashMap )。
下图是上述方法的试运行:
下面是上述方法的实现:
C++
// A C++ program to check if arr[0..n-1] can be divided
// in pairs such that every pair is divisible by k.
#include
using namespace std;
// Returns true if arr[0..n-1] can be divided into pairs
// with sum divisible by k.
bool canPairs(int arr[], int n, int k)
{
// An odd length array cannot be divided into pairs
if (n & 1)
return false;
// Create a frequency array to count occurrences
// of all remainders when divided by k.
unordered_map freq;
// Count occurrences of all remainders
for (int i = 0; i < n; i++)
freq[((arr[i] % k) + k) % k]++;
// Traverse input array and use freq[] to decide
// if given array can be divided in pairs
for (int i = 0; i < n; i++) {
// Remainder of current element
int rem = ((arr[i] % k) + k) % k;
// If remainder with current element divides
// k into two halves.
if (2 * rem == k) {
// Then there must be even occurrences of
// such remainder
if (freq[rem] % 2 != 0)
return false;
}
// If remainder is 0, then there must be two
// elements with 0 remainder
else if (rem == 0) {
if (freq[rem] & 1)
return false;
}
// Else number of occurrences of remainder
// must be equal to number of occurrences of
// k - remainder
else if (freq[rem] != freq[k - rem])
return false;
}
return true;
}
// Driver code
int main()
{
int arr[] = { 92, 75, 65, 48, 45, 35 };
int k = 10;
int n = sizeof(arr) / sizeof(arr[0]);
// Function call
canPairs(arr, n, k) ? cout << "True" : cout << "False";
return 0;
}
Java
// JAVA program to check if arr[0..n-1] can be divided
// in pairs such that every pair is divisible by k.
import java.util.HashMap;
public class Divisiblepair {
// Returns true if arr[0..n-1] can be divided into pairs
// with sum divisible by k.
static boolean canPairs(int ar[], int k)
{
// An odd length array cannot be divided into pairs
if (ar.length % 2 == 1)
return false;
// Create a frequency array to count occurrences
// of all remainders when divided by k.
HashMap hm = new HashMap<>();
// Count occurrences of all remainders
for (int i = 0; i < ar.length; i++) {
int rem = ((ar[i] % k) + k) % k;
if (!hm.containsKey(rem)) {
hm.put(rem, 0);
}
hm.put(rem, hm.get(rem) + 1);
}
// Traverse input array and use freq[] to decide
// if given array can be divided in pairs
for (int i = 0; i < ar.length; i++) {
// Remainder of current element
int rem = ((ar[i] % k) + k) % k;
// If remainder with current element divides
// k into two halves.
if (2 * rem == k) {
// Then there must be even occurrences of
// such remainder
if (hm.get(rem) % 2 == 1)
return false;
}
// If remainder is 0, then there must be two
// elements with 0 remainder
else if (rem == 0) {
// Then there must be even occurrences of
// such remainder
if (hm.get(rem) % 2 == 1)
return false;
}
// Else number of occurrences of remainder
// must be equal to number of occurrences of
// k - remainder
else {
if (hm.get(k - rem) != hm.get(rem))
return false;
}
}
return true;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 92, 75, 65, 48, 45, 35 };
int k = 10;
// Function call
boolean ans = canPairs(arr, k);
if (ans)
System.out.println("True");
else
System.out.println("False");
}
}
// This code is contributed by Rishabh Mahrsee
Python3
# Python3 program to check if
# arr[0..n-1] can be divided
# in pairs such that every
# pair is divisible by k.
from collections import defaultdict
# Returns true if arr[0..n-1] can be
# divided into pairs with sum
# divisible by k.
def canPairs(arr, n, k):
# An odd length array cannot
# be divided into pairs
if (n & 1):
return 0
# Create a frequency array to
# count occurrences of all
# remainders when divided by k.
freq = defaultdict(lambda: 0)
# Count occurrences of all remainders
for i in range(0, n):
freq[((arr[i] % k) + k) % k] += 1
# Traverse input array and use
# freq[] to decide if given array
# can be divided in pairs
for i in range(0, n):
# Remainder of current element
rem = ((arr[i] % k) + k) % k
# If remainder with current element
# divides k into two halves.
if (2 * rem == k):
# Then there must be even occurrences
# of such remainder
if (freq[rem] % 2 != 0):
return 0
# If remainder is 0, then there
# must be two elements with 0 remainde
elif (rem == 0):
if (freq[rem] & 1):
return 0
# Else number of occurrences of
# remainder must be equal to
# number of occurrences of
# k - remainder
elif (freq[rem] != freq[k - rem]):
return 0
return 1
# Driver code
arr = [92, 75, 65, 48, 45, 35]
k = 10
n = len(arr)
# Function call
if (canPairs(arr, n, k)):
print("True")
else:
print("False")
# This code is contributed by Stream_Cipher
C#
// C# program to check if arr[0..n-1]
// can be divided in pairs such that
// every pair is divisible by k.
using System.Collections.Generic;
using System;
class GFG {
// Returns true if arr[0..n-1] can be
// divided into pairs with sum
// divisible by k.
static bool canPairs(int[] ar, int k)
{
// An odd length array cannot
// be divided into pairs
if (ar.Length % 2 == 1)
return false;
// Create a frequency array to count
// occurrences of all remainders when
// divided by k.
Dictionary hm
= new Dictionary();
// Count occurrences of all remainders
for (int i = 0; i < ar.Length; i++) {
int rem = ((ar[i] % k) + k) % k;
if (!hm.ContainsKey(rem)) {
hm[rem] = 0;
}
hm[rem]++;
}
// Traverse input array and use freq[]
// to decide if given array can be
// divided in pairs
for (int i = 0; i < ar.Length; i++) {
// Remainder of current element
int rem = ((ar[i] % k) + k) % k;
// If remainder with current element
// divides k into two halves.
if (2 * rem == k) {
// Then there must be even occurrences
// of such remainder
if (hm[rem] % 2 == 1)
return false;
}
// If remainder is 0, then there
// must be two elements with 0
// remainder
else if (rem == 0) {
// Then there must be even occurrences
// of such remainder
if (hm[rem] % 2 == 1)
return false;
}
// Else number of occurrences of remainder
// must be equal to number of occurrences of
// k - remainder
else {
if (hm[k - rem] != hm[rem])
return false;
}
}
return true;
}
// Driver code
public static void Main()
{
int[] arr = { 92, 75, 65, 48, 45, 35 };
int k = 10;
// Function call
bool ans = canPairs(arr, k);
if (ans)
Console.WriteLine("True");
else
Console.WriteLine("False");
}
}
// This code is contributed by Stream_Cipher
Javascript
True
时间复杂度: O(n)。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。