C++で列の合計が行の合計より大きいペアの個数を数える方法
問題の概要
N×N のサイズの行列が与えられたとき、「列 j の要素の合計が行 i の要素の合計よりも大きい」という条件を満たすインデックスのペア (i, j) の総数を求めるのが目標です。
この問題は、行列を一度走査して各行・各列の要素の合計をあらかじめ計算しておくことで、効率よく解くことができます。
まず、各行の要素の合計を配列 rowsum[N] に、各列の要素の合計を配列 colsum[N] にそれぞれ格納します。
その後、rowsum[i] と colsum[j] のすべての組み合わせについて colsum[j] > rowsum[i] が成り立つかどうかを調べ、条件を満たすペアのカウントを増やしていきます。
それでは、具体例を使って理解しましょう。
具体例
例1
入力: matrix = {
{ 1,2,0,1},
{ 3,3,0,2},
{ 1,3,0,2},
{ 3,0,0,2}
};出力 − 有効なペアの個数 − 9
説明 −
Rowsum[0]= 1+2+0+1=5 Colsum[0]= 1+3+1+3=8 Rowsum[1]= 3+3+0+2=8 Colsum[1]= 2+3+3+0=8 Rowsum[2]= 1+3+0+2=6 Colsum[2]= 0+0+0+0=0 Rowsum[3]= 3+0+0+2=5 Colsum[3]= 1+2+2+2=7 rowsum[i] < colsum[j] を満たすペア (i,j): (0,0), (0,1), (0,3), (2,0), (2,1), (2,3), (3,0), (3,1), (3,3)
例2
入力: Arr[]= { {1,1,1}, {1,1,1}, {1,1,1} } N=3出力 − 有効なペアの個数 − 0
説明 −
Rowsum[0]= 1+1+1=3 Colsum[0]= 1+1+1=3 Rowsum[1]= 1+1+1=3 Colsum[1]= 1+1+1=3 Rowsum[2]= 1+1+1=3 Colsum[2]= 1+1+1=3 rowsum[i] < colsum[j] を満たすペアは存在しません
アルゴリズム(プログラムで使うアプローチ)
- ランダムな整数で初期化された整数型配列 Arr[] を用意します。
- 配列 Arr[] の長さを保持する変数 n を宣言します。
- 関数 countPairs(int arr[][3], int n) は、配列とその長さを引数として受け取り、条件を満たす有効なペアの個数を返します。
- 行の合計を格納する rowsum[n] と、列の合計を格納する colsum[n] の2つの配列を用意します。
- 行列を走査しながら arr[i][j] を rowsum[i] および colsum[j] に加算し、行 i と列 j の合計を計算します。
- 続いて、2重の for ループを使って rowsum[] と colsum[] を走査します。
- colsum[j] > rowsum[i] が成立した場合は、カウントを1つ増やします。
- 最後にカウントを結果として返します。
C++実装例
#include <bits/stdc++.h>
using namespace std;
int countPairs(int arr[][3], int n){
// ペアの個数
int count = 0;
int rowsum[n]={0};
int colsum[n]={0};
int i,j;
for (i = 0; i < n; i++){
for (j = 0; j < n; j++){
rowsum[i]+=arr[i][j];
colsum[j]+=arr[i][j];
}
}
for(i=0;i<n;i++){
for(j=0;j<n;j++)
if(colsum[j]>rowsum[i])
{ count++; }
}
return count;
}
int main(){
int Arr[][3] = { {1,3,5},{2,4,6},{3,5,7} };
int side=3;
cout <<endl<<"ペアの個数 : "<< countPairs(Arr, side);
return 0;
}出力
上記のコードを実行すると、次のような出力が得られます −
ペアの個数 : 4
計算量について
このアルゴリズムでは、行列の全要素を一度走査して行・列ごとの合計を求める処理に O(N²)、ペアの判定にも O(N²) の時間がかかるため、全体の時間計算量は O(N²) となります。また、補助配列 rowsum と colsum の分だけ、空間計算量は O(N) です。前計算により毎回行・列の合計を再計算せずに済むため、非常に効率的な手法と言えます。
-
C++で実装する!N未満で桁の和がNより大きい最大の数を求めるアルゴリズム
このチュートリアルでは、「Nより小さい数のうち、桁の和がNの桁の和よりも大きくなる最大の数」を求めるプログラムをC++で作成します。 問題の例 例えば、N = 75 の場合を考えてみましょう。75の桁の和は 7 + 5 = 12 です。このとき、75未満の数の中で桁の和が12を超える最大の数は 69(6 + 9 = 15)となります。 解決手順 桁の和を求める関数を作成します。 Nを初期化します。 n - 1 から 1 まで順に調べるループを記述します。 現在の数の桁の和とNの桁の和を比較します。 現在の数の桁の和の方が大きければ、その数を返します。 条件を満たさなければ、次の数へ進みま
-
C++でXとの合計がフィボナッチ数になるノードを数える方法
各ノードに数値の重みが割り当てられた二分木が与えられます。この記事の目的は、「ノードの重み + X」の計算結果がフィボナッチ数となるノードの個数を求めることです。フィボナッチ数列とは、0, 1, 1, 2, 3, 5, 8, 13… のように続く数列で、n番目の数は(n−1)番目と(n−2)番目の数の和になります。たとえば重みが13であればフィボナッチ数に該当するため、そのノードはカウント対象となります。入力例1temp = 1 の場合。値を入力すると、以下のような木が構成されます。出力Count the nodes whose sum with X is a Fibonacci number