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

【C++】有効な三角形の組み合わせ数を二ポインタ法で効率よく求める

非負整数のみから構成される配列が与えられ、その中から3つの要素を選んで三角形の3辺としたときに、実際に三角形を成立させられる組み合わせ(トリプレット)の総数を数えるのがこの問題です。

例えば、入力が [2, 2, 3, 4] の場合、答えは 3 になります。以下の3通りが有効な組み合わせだからです。

  • 1番目の「2」を使った [2, 3, 4]
  • 2番目の「2」を使った [2, 3, 4]
  • [2, 2, 3]

解法の鍵:三角形の成立条件

3辺 a、b、c(c を最長の辺とする)が三角形を成すための条件は、a + b > c が成り立つことです。この性質を利用すると、すべての組み合わせを総当たりで調べる O(n³) の方法よりも、ソート + 二ポインタ(ツーポインタ)法を組み合わせた O(n²) の効率的な解法が実現できます。

アルゴリズムの手順

  • ret := 0、n := 配列 nums のサイズとし、nums を昇順にソートします。
  • i を n − 1 から 0 まで降順にループし、最も長い辺となる候補 nums[i] を固定します。
    • right := i − 1、left := 0 と初期化します。
    • left < right である間、次の処理を繰り返します。
      • sum := nums[left] + nums[right] を計算します。
      • sum > nums[i] の場合、left から right までのすべての要素は nums[left] 以上であるため、その範囲内の任意のペアが条件を満たします。そこで ret に right − left を一括して加算し、right を 1 減らします。条件を満たさない場合は left を 1 増やして小さい側を調べ直します。
  • すべてのループが終わったら ret を返します。

この手法により、固定した最大の辺に対して残りの2辺の候補を線形時間で処理でき、全体の計算量は O(n²)、追加のメモリ使用量は O(1)(ソートに必要な分を除く)に抑えられます。

C++実装例

#include <bits/stdc++.h>
using namespace std;
class Solution {
   public:
   int triangleNumber(vector<int>& nums) {
      int ret = 0;
      int n = nums.size();
      sort(nums.begin(), nums.end());
      for(int i = n - 1; i >= 0; i--){
         int right = i - 1;
         int left = 0;
         while(left < right){
            int sum = nums[left] + nums[right];
            if(sum > nums[i]){
               ret += right - left;
               right--;
            }else left++;
         }
      }
      return ret;
   }
};
main(){
   vector<int> v = {2,2,3,4};
   Solution ob;
   cout << (ob.triangleNumber(v));
}

入力

[2,2,3,4]

出力

3

  1. C++で可変数の引数(可変長引数)を扱う方法

    プログラミングをしていると、引数の個数があらかじめ決まっていない関数、つまり呼び出しのたびに異なる数のパラメータを受け取れる関数が必要になる場面があります。C/C++ではこのような状況に対応する仕組みが用意されており、要件に応じて可変個の引数を受け取る関数を自由に定義できます。以下に、そのような関数の定義例を示します。 int func(int, ... ) { . . . } int main() { func(1, 2, 3); func(1, 2, 3, 4); } 注目すべきは、関数func()の最後の引数が省略記号(ピリオド3つの「...」)になってい

  2. C++のCHAR_BITとは?意味と使い方を解説

    CHAR_BITは、char型が持つビット数を表すマクロです。C++では「limits.h」ヘッダーファイル(C++では<climits>)で宣言されており、一般的な環境では1バイトが8ビットであることを示します。このマクロを利用することで、移植性の高いコードを書くことができます。環境に依存せずにchar型のビット数を取得できるため、ビット演算やデータサイズの計算に役立ちます。CHAR_BITの使用例以下は、C++でCHAR_BITを使用したサンプルコードです。CHAR_BITとsizeofを組み合わせてint型の全ビット数を求め、整数値を2進数形式で出力しています。#includ