C++で配列からnCr値が最大となるペアを検索する方法
概要
正の整数 n 個からなる配列 arr[] が与えられたとき、二項係数 arr[i]Carr[j] が最大となるような要素のペア arr[i] と arr[j] を配列から見つけるのが課題です。条件を満たすペアが複数存在する場合は、そのうちのいずれか1つを出力すれば構いません。
入力例
arr[] = {4, 1, 2}出力例
4 2 4C1 = 4 4C2 = 4 2C1 = 2 (4, 2) が nCr を最大化する唯一のペアです。
解法の考え方
nCr は n に関して単調増加する関数とみなせます。つまり n+1Cr > nCr が成り立ちます。この性質を利用することで答えに近づくことができます。まず、配列内のすべての整数の中から最大値を n として選びます。これにより n の値が確定します。
次に r に注目します。nCr = nCn-r という対称性があるため、nCr は最初に最大値に達し、その後減少していくことが分かります。
- n が奇数の場合: 最大値は n / 2 と n / 2 + 1 の位置で現れます。
例:n = 11 の場合、11C5 と 11C6 で最大値となります。 - n が偶数の場合: 最大値は n / 2 の位置で現れます。
例:n = 4 の場合、4C2 で最大値となります。
したがって、配列をソートした後、最大値 N を固定し、残りの要素の中から N / 2(奇数なら N / 2 または N / 2 + 1)に最も近い値を r として選べばよいことになります。
C++実装例
// この手法のC++実装
#include <bits/stdc++.h>
using namespace std;
// 最大の nCr を与えるペアを出力する関数
void printMaxValPair1(vector<long long>& v1, int n1){
sort(v1.begin(), v1.end());
// nCr における N の値
long long N1 = v1[n1 - 1];
// ケース1 : N1 が奇数の場合
if (N1 % 2 == 1) {
long long first_maxima1 = N1 / 2;
long long second_maxima1 = first_maxima1 + 1;
long long ans1 = 3e18, ans2 = 3e18;
long long from_left1 = -1, from_right1 = -1;
long long from = -1;
for (long long i = 0; i < n1; ++i) {
if (v1[i] > first_maxima1) {
from = i;
break;
}
else {
long long diff = first_maxima1 - v1[i];
if (diff < ans1) {
ans1 = diff;
from_left1 = v1[i];
}
}
}
from_right1 = v1[from];
long long diff1 = first_maxima1 - from_left1;
long long diff2 = from_right1 - second_maxima1;
if (diff1 < diff2)
cout << N1 << " " << from_left1;
else
cout << N1 << " " << from_right1;
}
// ケース2 : N1 が偶数の場合
else {
long long maxima = N1 / 2;
long long ans1 = 3e18;
long long R = -1;
for (long long i = 0; i < n1 - 1; ++i) {
long long diff = abs(v1[i] - maxima);
if (diff < ans1) {
ans1 = diff;
R = v1[i];
}
}
cout << N1 << " " << R;
}
}
// ドライバーコード
int main(){
vector<long long> v1 = { 1, 1, 2, 3, 6, 1 };
int n1 = v1.size();
printMaxValPair1(v1, n1);
return 0;
}実行結果
6 3
まとめ
このアルゴリズムでは、配列を一度ソートするだけでよく、その後は線形探索によって最適な r を求めます。計算量は O(n log n) であり、実際に巨大な二項係数を計算することなく最大の nCr を持つペアを効率的に特定できる点が大きな特徴です。
-
C++でXとの絶対差が最小となるノードを見つける方法
問題の概要木構造と各ノードの重み、そして整数 x が与えられたとき、|weight[i] − x| の値が最小となるノード i を見つける問題を考えてみましょう。例えば、下図のような木があり、x = 15 とします。この場合、出力は 3 となります。各ノードについて絶対差を計算すると、以下のようになります。ノード 1:|5 − 15| = 10ノード 2:|10 − 15| = 5ノード 3:|11 − 15| = 4ノード 4:|8 − 15| = 7ノード 5:|6 − 15| = 9絶対差が最小となるのはノード 3 の「4」であるため、答えは 3 です。アルゴリズムの考え方アプローチは非
-
Pythonで配列内のnCr値が最大となるペアを検索する方法
問題概要 n個の整数を含む配列arrが与えられたとき、配列からarr[i]とarr[j]を選び、二項係数arr[i]Carr[j](組み合わせの数)が最大になるようなペアを見つける必要があります。条件を満たすペアが複数存在する場合は、そのうちのどれか1つを返せば構いません。 例えば、入力が[4, 1, 2]の場合、出力は「4 2」になります。これは、4C1 = 4、4C2 = 6、2C1 = 2と計算でき、(4, 2)のペアが最大値6を与える唯一の組み合わせだからです。 解法の考え方 この問題を効率的に解くには、二項係数の重要な性質を利用します。nCrは、rがn/2に最も近いときに最大値を取る