C++で合計が0になるN個の一意な整数の配列を生成する方法
問題概要
整数 n が与えられたとき、合計が 0 になる n 個の「一意な(重複しない)整数」を含む配列を返すことを考えます。たとえば、入力が n = 5 の場合、[-7, -1, 1, 3, 4] のような配列が有効な答えのひとつになります。
解法のアプローチ
この問題は、非常にシンプルな発想で解くことができます。1 から n-1 までの整数を順に配列に格納しながら、それらの合計を記録しておきます。最後に、その合計の符号を反転した値を配列の末尾に追加すれば、配列全体の合計は必ず 0 になります。
具体的な手順は以下の通りです。
- 答えとなる配列 A を用意し、変数 x を 0 で初期化します。
- i を 0 から n-2 までの範囲でループします。
- A[i] = (i + 1) とします。
- x := x + i + 1 で合計を更新します。
- A[n-1] = -x とし、合計の符号を反転した値を格納します。
- 配列 A を返します。
この方法では、最初の n-1 個の要素はすべて正の異なる整数(1, 2, ..., n-1)であるため重複が発生せず、最後の要素 -x がそれらの合計をちょうど打ち消すため、条件を満たす配列が必ず得られます。計算量は O(n) と非常に効率的です。
C++での実装例
以下に、実際のC++コードを示します。
#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<int> v){
cout << "[";
for(int i = 0; i<v.size(); i++){
cout << v[i] << ", ";
}
cout << "]"<<endl;
}
class Solution {
public:
vector<int> sumZero(int n) {
vector <int> ans(n);
int x = 0;
for(int i = 0; i < n - 1; i++){
ans[i] = (i + 1);
x += (i + 1);
}
ans[n - 1] = -x;
return ans;
}
};
main(){
Solution ob;
print_vector(ob.sumZero(10)) ;
}入力
10
出力
[1, 2, 3, 4, 5, 6, 7, 8, 9, -45]
この出力では、1 から 9 までの整数と、その合計 45 の符号を反転した -45 が含まれており、配列全体の合計が 0 になっていることが確認できます。
-
C++で二分木の最大レベル和を求める方法
問題概要 この問題では、正と負の値を含む二分木が与えられます。私たちのタスクは、二分木におけるレベル和の最大値を見つけることです。 問題の説明: 与えられた二分木に対して、各レベルに存在するすべてのノードの値の合計を計算し、その中で最も大きい値を返します。 具体例を使って問題を理解しましょう。 入力: 出力: 5 説明: レベル1の要素の合計:3 レベル2の要素の合計:-3 + 4 = 1 レベル3の要素の合計:5 - 1 + 6 - 5 = 5 各レベルの合計は「3」「1」「5」となるため、最大のレベル和は 5 となります。 解法アプローチ この問題を効率的に解くには、レベル順走査(幅優先
-
C++で二分木における最大部分木の合計を求める方法
この問題では、二分木(バイナリツリー)が与えられます。私たちのタスクは、木の中で最も大きな合計値を持つ部分木を見つけることです。 問題の概要 二分木には正の値と負の値が混在しています。その中から、ノードの合計が最大になる部分木を特定する必要があります。 例で問題を理解しよう 出力: 13 説明: 左部分木の合計:7 右部分木の合計:1 木全体の合計:13 このように、根を含む木全体の合計である「13」が最大の部分木の合計となります。 解法のアプローチ この問題を解くためには、後順走査(ポストオーダー走査)を利用します。手順は以下の通りです。 左部分木と右部分木それぞれのノードの合計を再