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

C++で非増加順(降順)ソートされたvectorの下限と上限を求める方法

本記事では、C++ STLにおいて非増加順(降順)にソートされた配列に対して、vector::lower_bound()およびvector::upper_bound()を使用する方法について詳しく解説します。

vectorとは

vectorは動的配列に近い性質を持つコンテナです。要素の挿入や削除を行うと、必要に応じて自身のサイズを自動的に拡張・縮小できるため、要素数が事前に確定していない場合でも柔軟にデータを管理できます。

lower_boundとupper_boundの動作

降順にソートされたvectorに対しては、次のようなイテレータが返されます。

  • lower_bound():指定した値「以下」の要素が最初に現れる位置を指すイテレータを返します。
  • upper_bound():指定した値「未満」の要素が最初に現れる位置を指すイテレータを返します。

入力例

30 30 30 20 20 20 10 10

出力例

20のlower_bound = 3
20のupper_bound = 6

入力例

9 9 8 8 8 7 7 7 6 6 6 6

出力例

7のlower_bound = 5
7のupper_bound = 8

戻り値

lower_bound()は同値範囲の先頭要素を指すイテレータを返し、upper_bound()は同値範囲の末尾要素の次の位置を指すイテレータを返します。つまり、両者の間には「指定した値と等しいすべての要素」が含まれることになります。

実装の手順

  • まずvectorを初期化します。
  • vectorの要素をgreater<int>()を使って降順(非増加順)にソートします。
  • lower_bound()で下限を求めます。
  • upper_bound()で上限を求めます。
  • 最後に両方の結果を出力します。

重要なポイント: 降順にソートされたvectorに対してlower_bound()/upper_bound()を正しく動作させるには、第4引数として比較関数オブジェクトgreater<int>()を渡す必要があります。これを省略すると誤った結果になります。また、ソートされていないvectorに対してこれらの関数を使用することはできません。

サンプルコード1

// lower_boundとupper_boundの動作を示すC++プログラム
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

int main() {
    int vect[] = {13, 13, 13, 16, 16, 16, 17, 17, 17, 17, 18, 18};
    vector<int> v(vect, vect + 12);

    // 降順にソート
    sort(v.begin(), v.end(), greater<int>());

    cout << "\nSorted Vector: ";
    for (auto i = v.begin(); i != v.end(); ++i)
        cout << *i << " ";
    cout << "\n";

    vector<int>::iterator low, up;
    low = lower_bound(v.begin(), v.end(), 17, greater<int>());
    up = upper_bound(v.begin(), v.end(), 17, greater<int>());

    cout << "Lower bound = " << (low - v.begin()) << "\n";
    cout << "Upper bound = " << (up - v.begin()) << "\n";
    return 0;
}

出力

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

Sorted Vector: 18 18 17 17 17 17 16 16 16 13 13 13
Lower bound = 2
Upper bound = 6

サンプルコード2

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

int main() {
    int vect[] = {5, 5, 5, 5, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10};
    vector<int> v(vect, vect + 16);

    // 降順にソート
    sort(v.begin(), v.end(), greater<int>());

    cout << "\nSorted Vector: ";
    for (auto i = v.begin(); i != v.end(); ++i)
        cout << *i << " ";
    cout << "\n";

    vector<int>::iterator low, up;
    low = lower_bound(v.begin(), v.end(), 8, greater<int>());
    up = upper_bound(v.begin(), v.end(), 8, greater<int>());

    cout << "Lower bound = " << (low - v.begin()) << "\n";
    cout << "Upper bound = " << (up - v.begin()) << "\n";
    return 0;
}

出力

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

Sorted Vector: 10 10 9 9 9 8 8 8 8 7 7 7 5 5 5 5
Lower bound = 5
Upper bound = 9

まとめ

降順ソートされたvectorから特定の値の範囲を取得する場合は、sort()・lower_bound()・upper_bound()のすべてにgreater<int>()を渡すことが重要です。これにより二分探索が正しく機能し、同値要素の開始位置と終了位置をO(log n)の計算量で効率的に求められます。

  1. C++で直方体の体積と表面積を計算するプログラムの作成方法

    直方体とは? 直方体とは、6つの長方形の面から構成される三次元の立体図形です。各面の縦と横の長さが異なるため、全体として異なる長さの辺を持っています。立方体と直方体の違いは、立方体では長さ・高さ・幅がすべて等しいのに対し、直方体ではこれら3つが必ずしも同じではないという点です。 直方体の主な性質は以下のとおりです。 6つの面 12本の辺 8つの頂点 以下は直方体のイメージ図です。 問題の概要 直方体の長さ(L)、幅(W)、高さ(H)が与えられたとき、その総表面積と体積を求めるのが課題です。表面積とは各面が占める空間の広さのことであり、体積とはその形状が内包できる空間の大きさのことです。

  2. C++で立方体の体積と表面積を求めるプログラム

    立方体とは? 立方体とは、正方形の面を6つ持つ三次元の立体図形です。すべての辺の長さが等しいという特徴があります。立方体は唯一の正六面体であり、以下のような性質を持ちます。 面の数:6つ 辺の数:12本 頂点の数:8つ 以下は立方体の図です。 問題の概要 立方体の一辺の長さが与えられたとき、その立方体の表面積と体積を求めることが課題です。ここで、表面積とは立方体の各面が占める面積の合計を指し、体積とはその図形が内包できる空間の大きさを指します。 立方体の表面積と体積を計算するには、次の公式を使用します。 表面積 = 6 × 辺 × 辺 体積 = 辺 × 辺 × 辺 入力例と出力例 入力