C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で積が最小となるトリプレットの個数を数える方法

整数型の配列 Arr[] が与えられたとします。この記事のゴールは、考えられるすべてのトリプレット(三つ組)の中で「積」が最小になる組み合わせの個数を数えることです。具体的には、i < j < k を満たし、arr[i] * arr[j] * arr[k] が最小値となるトリプレットを対象にします。

解決の手順としては、まず i < j < k の条件下で実現可能な最小の積を求め、それを minprod として記録します。その後、積が minprod と一致するトリプレットをすべて数え上げます。

具体例で理解しよう

入力 − arr[] = { 1, 2, 3, 2, 4, 1, 5 }

出力 − トリプレットの個数:2

説明 −

この配列における最小の積は 2 です。
トリプレット1 [ 1,2,3,2,4,1,5 ] → (1,2,1) 積 = 2
トリプレット2 [ 1,2,3,2,4,1,5 ] → (1,2,1) 積 = 2
最小の積 2 を持つトリプレットは合計 2 個です。

入力 − arr[] = { 1, 1, 2, 1, 2, 2 }

出力 − トリプレットの個数:1

説明 −

この配列における最小の積は 1 です。
トリプレット1 [ 1,1,2,1,2,2 ] → (1,1,1) 積 = 1
最小の積 1 を持つトリプレットは合計 1 個です。

プログラムで使用するアプローチ

  • ランダムな値で初期化された整数型配列 Arr[] を用意します。
  • 配列 Arr[] の長さを格納する変数 N を用意します。
  • 関数 countTriplets(int arr[], int n) は、配列とその長さを引数に取り、積が最小積と一致するトリプレットの個数を返します。
  • トリプレットの個数を数えるための変数 count を 0 で初期化します。
  • 各トリプレットの積を保持する変数 prod を用意し、初期値は 1 とします。
  • すべてのトリプレットの中で最小の積を保持する変数 minprod を用意し、初期値は十分大きな値(9999)とします。
  • 3重の for ループを使って、トリプレットを構成する各要素を走査します。
  • 外側のループは 0 ≤ i < n-2、内側のループは i < j < n-1、最も内側のループは j < k < n の範囲で動作します。
  • prod = arr[i] * arr[j] * arr[k] を計算し、prod ≤ minprod であれば minprod を prod で更新します。
  • この時点で、minprod にはすべてのトリプレットの中で最小の積が格納されています。
  • 再度、3重の for ループを使って配列を走査します。
  • ループの範囲は先ほどと同じく、0 ≤ i < n-2、i < j < n-1、j < k < n です。
  • prod = arr[i] * arr[j] * arr[k] を計算し、prod == minprod であれば count をインクリメントします。これはそのトリプレットが最小の積を持つことを意味します。
  • すべてのループが終了した時点で、count には条件を満たすトリプレットの総数が格納されています。
  • count を結果として返します。

実装例

#include <bits/stdc++.h>
using namespace std;
int countTriplets(int arr[], int n){
    int count = 0;
    int prod = 1;
    int minprod = 9999; // 配列内のどの積よりも大きい値で初期化
    for (int i = 0; i < n-2; i++){
        for (int j = i+1; j < n-1; j++){
            for (int k = j+1; k < n; k++){
                prod = arr[i]*arr[j]*arr[k];
                if ( prod <= minprod )
                    { minprod = prod; }
            }
        }
    }
    // cout<<"minproduct :"<<minprod; // 最小の積を表示する場合
    for (int i = 0; i < n-2; i++){
        for (int j = i+1; j < n-1; j++){
            for (int k = j+1; k < n; k++){
                prod = arr[i]*arr[j]*arr[k];
                if ( prod == minprod ){
                    count++;
                    // cout<<endl<<"a :"<<arr[i]<<" b :"<<arr[j]<<" c :"<<arr[k]; // 表示する場合
                }
            }
        }
    }
    return count;
}
int main(){
    int Arr[]={ 1,2,3,1,2,6};
    int N=5; // 配列の長さ
    cout << endl << "Number of triplets : " << countTriplets(Arr,N);
    return 0;
}

出力

上記のコードを実行すると、次の出力が生成されます。

Number of triplets : 2
  1. C++で集合をk個の部分集合に分割する方法の総数を動的計画法で求める

    2つの数 e(要素数) と p(分割数) が与えられたとき、「集合の e 個の要素を p 個の部分集合(パーティション)に分割する方法が全部で何通りあるか」を求めるのがこの問題の目的です。 例1 入力 e=4 p=2 出力 Count of number of ways to partition a set into k subsets are: 7 説明 要素が a・b・c・d の4つである場合、これらを2つのグループに分ける方法は次の7通りあります。 (a)−(b,c,d)、(b)−(a,c,d)、(c)−(a,b,d)、(d)−(a,b,c)、(a,b)−(c,d)、(a,c)−(b,

  2. ソート済み双方向連結リストで積が指定値xと等しくなるトリプルの個数を数えるC++プログラム

    問題の概要 整数値を格納したソート済みの双方向連結リスト(doubly linked list)が与えられます。この課題の目標は、3つのノードのデータの積が指定された値xと等しくなるようなトリプル(三つ組)の個数を求めることです。 例えば、入力リンクリストが「3→4→1→2」でxが6の場合、積が6になるトリプルは(3, 1, 2)の1つだけなので、カウントは1となります。 入力例と出力例 例1 入力: linked list: [ 200→4→16→5→10→10→2 ]、x = 200 出力: 積が指定値xと等しくなるトリプルの個数: 3 説明: 該当するトリプルは以下の3つです。 (4