C++で3の倍数の最大値を求めるアルゴリズムを解説
数字の配列が与えられたとき、その中から任意の個数の数字を選び、好きな順序で連結して作ることができる「3の倍数」の最大値を求めます。答えは非常に大きな数になる可能性があるため、文字列として返します。条件を満たす組み合わせが存在しない場合は、空文字列を返します。
たとえば、入力が [7, 2, 8] の場合、出力は 87 になります。
解法のポイント
この問題を解く鍵となるのは、「ある整数が3の倍数であること」と「その各位の数字の総和が3の倍数であること」が同値であるという有名な性質です。これを利用すると、次のような戦略が立てられます。
3行からなる2次元配列 d を定義する(d[x mod 3] には「3で割った余りが x」に相当する数字を格納)
配列 digits を降順にソートする
sum := 0 で初期化する
i := 0 から digits のサイズ未満まで、i を1ずつ増やしながら繰り返す:
x := digits[i]
d[x mod 3] の末尾に digits[i] を追加する
sum := sum + x とし、続けて sum := sum mod 3 とする
sum が 0 以外の場合:
d[sum] が空の場合:
rem := 3 - sum とする
d[rem] のサイズが 2 未満であれば、空文字列を返す
d[rem] の末尾から要素を2つ削除する
それ以外の場合:
d[sum] の末尾から要素を1つ削除する
ret := 空文字列 で初期化する
i := 0 から 2 まで繰り返し、各 d[i] のすべての要素を文字列として ret に連結する
ret を降順にソートする
ret のサイズが 0 より大きく、先頭文字が '0' である場合は "0" を返す
ret を返す
ここで重要なのは、sum が 1 のときは「余り 1 の数字を1つ」または「余り 2 の数字を2つ」取り除けばよく、sum が 2 のときも同様の発想で対応できるという点です。あらかじめ降順にソートしておけば、削除対象は常に配列の末尾(最も小さい数字)になるため、処理がシンプルになります。
それでは、以下の実装例を見て理解を深めましょう。
実装例(C++)
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
string largestMultipleOfThree(vector<int>& digits) {
vector<vector<int>> d(3);
sort(digits.begin(), digits.end(), greater<int>());
int sum = 0;
for (int i = 0; i < digits.size(); i++) {
int x = digits[i];
d[x % 3].push_back(digits[i]);
sum += x;
sum %= 3;
}
if (sum) {
if (!d[sum].size()) {
int rem = 3 - sum;
if (d[rem].size() < 2)
return "";
d[rem].pop_back();
d[rem].pop_back();
}
else {
d[sum].pop_back();
}
}
string ret = "";
for (int i = 0; i < 3; i++) {
for (int j = 0; j < d[i].size(); j++) {
ret += to_string(d[i][j]);
}
}
sort(ret.begin(), ret.end(), greater<int>());
if (ret.size() && ret[0] == '0')
return "0";
return ret;
}
};
main(){
Solution ob;
vector<int> v = {7,2,8};
cout << (ob.largestMultipleOfThree(v));
}
入力
{7,2,8}
出力
87
-
C++で二分木における最大部分木の合計を求める方法
この問題では、二分木(バイナリツリー)が与えられます。私たちのタスクは、木の中で最も大きな合計値を持つ部分木を見つけることです。 問題の概要 二分木には正の値と負の値が混在しています。その中から、ノードの合計が最大になる部分木を特定する必要があります。 例で問題を理解しよう 出力: 13 説明: 左部分木の合計:7 右部分木の合計:1 木全体の合計:13 このように、根を含む木全体の合計である「13」が最大の部分木の合計となります。 解法のアプローチ この問題を解くためには、後順走査(ポストオーダー走査)を利用します。手順は以下の通りです。 左部分木と右部分木それぞれのノードの合計を再
-
3つの数字の中から最大値を見つけるC++プログラム
3つの数値の中から最大のものを求めるには、if文を組み合わせて条件分岐を行うのが基本的な方法です。ここでは、if文を入れ子構造にして最大値を判定するC++プログラムを紹介します。 サンプルコード #include <iostream> using namespace std; int main() { int a = 5 ,b = 1 ,c = 9; if(a>b) { if(a>c) cout<<a<<&quo