C++でarr[i]*iの合計を最大化する方法
問題の概要
N個の整数からなる配列が与えられます。配列の要素は自由に並べ替えることができます。そのうえで、Σarr[i] * i(i = 0, 1, 2, ... n-1)の最大値を求めるのが課題です。
例えば、入力配列が {4, 1, 6, 2} の場合、要素を昇順に並べ替えることで最大値28が得られます。
{1, 2, 4, 6} = (1 * 0) + (2 * 1) + (4 * 2) + (6 * 3) = 28アルゴリズム
この問題は、次の手順で解くことができます。
- 配列を昇順にソートする
- 配列を走査し、各要素にインデックスi(0, 1, 2, ..., n-1)を掛けて合計する
- 合計値を返す
なぜ昇順ソートが最適なのでしょうか。理由はシンプルで、大きな値ほど大きなインデックスと掛け合わせたほうが合計が大きくなるためです。もし小さな値が後ろに配置されると、それをより大きな値と入れ替えたときに必ず合計が増加するため、昇順配置が理論上の最大値となります。
実装例(C++)
#include <bits/stdc++.h>
using namespace std;
int getMaxSum(int *arr, int n){
sort(arr, arr + n);
int sum = 0;
for (int i = 0; i < n; ++i) {
sum = sum + arr[i] * i;
}
return sum;
}
int main(){
int arr[] = {4, 1, 6, 2};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Maximum sum = " << getMaxSum(arr, n) << endl;
return 0;
}
出力結果
上記のプログラムをコンパイルして実行すると、次の出力が得られます。
Maximum sum = 28
計算量について
このアルゴリズムの時間計算量はO(n log n)で、これはソート処理のコストが支配的であるためです。ソート後の走査は線形時間O(n)で完了します。また、追加のメモリを使用しないため、空間計算量はO(1)です。
-
C++で解く迷路問題:転がるボールが目的地に止まれるかをBFSで判定する方法
迷路の中にボールがあるとします。迷路には空きスペース(通路)と壁があります。ボールは上下左右のいずれかの方向に転がって空き通路を進むことができますが、壁にぶつかるまで止まりません。ボールが停止したときに、次の方向を選べます。この問題では、ボールの開始位置、目的地、そして迷路そのものが与えられ、「ボールが目的地の位置で停止できるかどうか」を判定する必要があります。迷路は2次元配列で表現され、1は壁、0は空きスペースを意味します。迷路の外周はすべて壁になっています。開始位置と目的地は行・列のインデックス(座標)で与えられます。問題例たとえば、次のような2次元配列で表される迷路を考えてみましょう。0
-
【C++】循環リンクリストのノード値の合計を求める方法
この記事では、循環リンクリスト(Circular Linked List)が与えられたときに、すべてのノードの値の合計を求めるプログラムをC++で作成する方法を解説します。 やるべきことはシンプルで、リンクリストを構成する全ノードの値を順番に読み取り、それらを加算していくだけです。 前提知識:重要な定義 リンクリストとは リンクリスト(連結リスト)とは、各データ(ノード)をポインタによるリンクで相互に接続したデータ構造の列です。配列と異なり、メモリ上の連続した領域を必要とせず、動的な挿入や削除に強いという特徴があります。 循環リンクリストとは 循環リンクリストはリンクリストの変形の一種で、先