C++で各変数が1つ欠けたn個の和の方程式からn個の変数を求める方法
この問題では、(n−1)個の変数の和から構成される配列 sum[] が与えられます。各要素は、対応する1つの変数を除いた残りすべての変数の和を表しています。
Sum[1] = x2 + x3 + x4 + … + xn Sum[2] = x1 + x3 + x4 + … + xn . . Sum[i] = x1 + … + x(i-1) + x(i+1) + … + xn . . Sum[n] = x1 + x2 + x3 + … + x(n-1)
この記事のゴールは、これらの式から x1, x2, …, xn の値を求めることです。
入力例
sum[] = {6, 6, 6, 6, 6, 6, 6}
出力例
x1 = 1, x2 = 1, x3 = 1, x4 = 1, x5 = 1, x6 = 1, x7 = 1
説明
arr[1] = 1 + 1 + 1 + 1 + 1 + 1 = 6
解法アプローチ
まず、すべての変数の総和を sumX と定義します。
sumX = x1 + x2 + x3 + … + xn
すると、sum 配列の各要素は次のように書き換えられます。
sum[1] = x2 + x3 + x4 + … + xn
= -x1 + (x1 + x2 + x3 + … + xn)
= sumX - x1
同様に、以下の関係が成り立ちます。
sum[2] = sumX - x2 sum[3] = sumX - x3 . sum[i] = sumX - xi . sum[n] = sumX - xn
次に、sum 配列の全要素を合計してみましょう。
Sum[1] + Sum[2] + … + Sum[n] = (sumX - x1) + (sumX - x2) + … + (sumX - xn) arrSum = n × sumX - (x1 + x2 + x3 + … + xn) arrSum = n × sumX - sumX arrSum = sumX × (n - 1)
したがって、総和 sumX は次の式で求められます。
sumX = arrSum / (n - 1)
この sumX の値が分かれば、各変数は「総和から対応する sum の値を引く」だけで簡単に計算できます。
x1 = sumX - sum[1] x2 = sumX - sum[2] .. xi = sumX - sum[i] .. xn = sumX - sum[n]
計算量
配列の走査は2回だけで済むため、時間計算量は O(n)、追加メモリも不要で空間計算量は O(1) と非常に効率的です。
C++実装例
上記の解法の動作を示すプログラムは以下の通りです。
#include <iostream>
using namespace std;
void calcSumVariables(int sum[], int n) {
float SUMX = 0;
for (int i = 0; i < n; i++) {
SUMX += sum[i];
}
SUMX /= (n - 1);
for (int i = 0; i < n; i++)
cout << "\nx" << (i + 1) << " = " << (SUMX - sum[i]);
}
int main(){
int sum[] = {3, 8, 6, 7, 4, 5, 9 };
int N = sizeof(sum) / sizeof(sum[0]);
cout << "The value of variables that form the sum are ";
calcSumVariables(sum, N);
return 0;
}
出力
x1 = 4 x2 = -1 x3 = 1 x4 = 0 x5 = 3 x6 = 2 x7 = -2
このように、総和 sumX を一度求めてしまえば、あとは引き算だけで n 個の変数すべてを復元できることが分かります。連立方程式を直接解く必要がないため、実装もシンプルになります。
-
C++で平衡二分探索木から目標合計となるペアを見つける方法
平衡二分探索木(Balanced BST)と目標値(target sum)が与えられたとき、合計が目標値と等しくなるペアが木の中に存在するかどうかを判定するメソッドを実装することを考えます。この際、二分探索木は不変(immutable)である、つまり木の構造を変更してはいけないという制約があることに注意が必要です。例えば、入力が以下のような木だったとします。この場合、出力は (9 + 26 = 35) となります。解決アプローチこの問題は、ソート済み配列でよく使われる「二ポインタ(Two Pointers)」手法を、二分探索木に応用することで解けます。具体的には、以下の2つの走査を同時に進めて
-
C++を使って行列内で合計が最大の列を見つける方法
ここでは、サイズ M × N の行列が与えられたときに、要素の合計が最大となる列を見つける方法を解説します。この問題では、難しいアルゴリズムを用いる必要はありません。行列を列方向に走査して各列の合計値を計算し、その合計が最大であれば、合計値と該当する列のインデックスを出力するというシンプルなアプローチで十分です。アルゴリズムの手順処理の流れは以下の通りです。1. 最大合計値を格納する変数 maxSum を INT_MIN で初期化し、列のインデックスを格納する index を -1 に設定します。2. 各列(0 ~ N-1)について、colSum 関数を使ってその列の要素の合計を計算します。3