C++で最も視聴された上位k番組の合計視聴時間を求める方法
テレビ番組のリストと、それぞれの視聴時間のリスト、さらに整数 k が与えられたとします。shows[i] と duration[i] は、i 番目の人が視聴した番組名とその視聴時間を表しています。このとき、最も視聴時間の長い上位 k 個の番組の合計視聴時間を求めるのが本記事の目的です。
問題の例
例えば、入力が以下のような場合を考えてみましょう。
- shows: ["Castle Play", "Fairy Tale Series", "Castle Play", "Jerry Mouse", "Rich Boy"]
- duration: [6, 4, 6, 14, 5]
- k = 2
この場合の出力は 26 になります。
理由を見てみると、「Castle Play」は2回登場するため合計視聴時間は 6 + 6 = 12 分、「Jerry Mouse」は 14 分です。これら上位2番組の合計は 12 + 14 = 26 となるため、答えは 26 になります。
解決のためのアルゴリズム
この問題は、以下の手順で解くことができます。
- map<string, int> 型のマップ m を定義します。
- n := ベクトル v のサイズとします。
- i を 0 から n-1 までループし、m[v[i]] += d[i] として各番組の視聴時間を累積します。
- 配列 arr を定義します。
- マップ m の各キーと値のペアに対して、値(合計視聴時間)を arr の末尾に追加します。
- arr を降順にソートします。
- ret := 0 と初期化します。
- i を 0 から k-1 までループし、ret += arr[i] として上位 k 件の視聴時間を合計します。
- ret を返します。
C++での実装例
理解を深めるために、実際のコードを見てみましょう。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int solve(vector<string>& v, vector<int>& d, int k) {
map <string, int> m;
int n = v.size();
for(int i = 0; i < n; i++){
m[v[i]] += d[i];
}
vector < int > arr;
for(auto it : m){
arr.push_back(it.second);
}
sort(arr.rbegin(), arr.rend());
int ret = 0;
for(int i = 0; i < k; i++){
ret += arr[i];
}
return ret;
}
};
int main(){
vector<string> v = {"Castle Play", "Fairy Tale Series", "Castle
Play", "Jerry Mouse", "Rich Boy"};
vector<int> v1 = {6, 4, 6, 14, 5};
Solution ob;
cout << (ob.solve(v, v1, 2));
}入力
{"Castle Play", "Fairy Tale Series", "Castle Play", "Jerry Mouse",
"Rich Boy"}, {6, 4, 6, 14, 5}, 2出力
26
コードのポイント解説
この実装では、まず std::map を使って同じ番組名の視聴時間を自動的に集計しています。map のキーは番組名、値は累積視聴時間です。
次に、集計結果を vector に取り出し、rbegin() と rend() を使った降順ソートを行うことで、視聴時間の長い順に並べ替えています。
最後に先頭から k 件分を足し合わせるだけで、求めたい合計視聴時間が得られます。計算量は O(n log n)(ソート部分が支配的)であり、非常にシンプルかつ効率的なアプローチです。
-
C++で解くリスのナッツ収集シミュレーション ― 最小移動距離を求めるアルゴリズム
問題概要 1本の木、1匹のリス、そして複数のナッツがフィールド上にあります。それぞれの位置は2次元グリッドのセルで表現されます。この問題の目的は、リスがすべてのナッツを集めて木の下に1個ずつ運ぶときの最小移動距離を求めることです。 リスの行動には次の制約があります。 一度に持てるナッツは最大1個 移動は上下左右の4方向で、隣接するセルへのみ可能 距離は移動回数(ステップ数)で表される たとえば、入力が「高さ: 5 / 幅: 7 / 木の位置: [2,2] / リスの位置: [4,4] / ナッツ: [[3,0], [2,5]]」の場合、出力は 12 となります。 解法のポイント まず、
-
C++で解く長方形エリアII ― 座標圧縮と走査線法による被覆面積の計算
問題概要 軸に平行な長方形のリストが与えられるものとします。各 rectangle[i] = {x1, y1, x2, y2} において、(x1, y1) は i 番目の長方形の左下隅の座標、(x2, y2) は右上隅の座標を表します。 求めたいのは、平面上でこれらすべての長方形が覆っている領域の合計面積です。答えは非常に大きな値になる可能性があるため、109 + 7 で割った余りを返すことになっています。 たとえば、入力が次のような場合を考えてみましょう。 このとき、出力は 6 となります。 解法の方針:座標圧縮+走査線(スイープライン) この問題は、座標圧縮(座標の離散化)と走査線法(