-
C++で1から3999までの10進数をローマ数字に変換する方法
はじめにこのチュートリアルでは、1から3999の範囲にある10進数をローマ数字に変換するC++プログラムについて解説します。ローマ数字は、I(1)、V(5)、X(10)、L(50)、C(100)、D(500)、M(1000)といった記号の組み合わせで数を表す古代ローマの記数法です。さらに、減算則(IがVやXの直前に置かれる場合は4や9を表すなど)にも対応する必要があります。本プログラムでは、ランダムな整数が与えられたとき、その数値を対応するローマ数字へ変換することを目標とします。アルゴリズムの考え方変換には貪欲法(greedy algorithm)を用います。手順は以下の通りです。基本となる数
-
C++で母音と子音を交互に配置した文字列を生成する方法
与えられた文字列に対して、母音と子音が交互に現れるように文字を並べ替えることを考えます。適切に並べ替えられない場合は「no such string」と表示してください。また、母音同士・子音同士の相対的な順序は元の文字列のまま維持する必要があります。条件を満たす文字列が複数存在する場合は、辞書順で最も小さいものを出力します。入出力例入力 : Tutorial 出力 : Tutorila 入力 : onse 出力 : nose「onse」の場合、「nose」と「ones」の2通りが考えられます。このうち「nose」の方が辞書順で小さいため、こちらを出力します。解法のアプローチまず、与えられた文字
-
C++での文字列変換のインプレースアルゴリズム:サイクルリーダー法によるO(n)実装
与えられた文字列に対して、偶数番目の要素をすべて文字列の末尾へ移動する問題を考えます。ただし、要素を移動する際には、偶数番目・奇数番目それぞれのグループ内での相対的な順序を維持しなければなりません。 例えば、入力文字列が「a1b2c3d4e5f6g7h8i9j1k2l3m4」である場合、「abcdefghijklm1234567891234」へ、追加メモリを使わないインプレース処理かつ O(n) の時間計算量で変換します。 アルゴリズムの手順 サイズが 3k + 1 の形となる最大の接頭辞部分文字列を切り出します。このステップでは、3k + 1 が n(文字列の長さ)以下となる最大の非負整
-
C++で代替セグメントの角が与えられた場合の、弦と接線のなす角を求める方法
円が与えられている場合、弦と接線はある一点で交わります。ここでの目的は、代替セグメント(弦の反対側の領域)における角が既知であるとき、弦と接線のなす角を求めることです。 実は、この問題には美しい幾何学的性質が隠されています。「接弦の角定理」によれば、弦と接線のなす角は、その弦に対する反対側の円周角(代替セグメントの角)と必ず等しくなります。以下で、その証明の流れとプログラムの実装を見ていきましょう。 例 Input: z = 40 Output: 40 degrees Input: z = 60 Output: 60 degrees 証明のアプローチ 角QPRを、代替セグメントにおける既知
-
C++の配列メンバーはディープコピーされる?構造体・クラス代入の仕組みを解説
C/C++では、同じ型の構造体変数(C++ではクラスのオブジェクトも同様)を、別の変数に代入することができます。この代入が行われると、元の変数のすべてのメンバーが相手側の構造体変数へコピーされます。ここで一つ疑問が生じます。「構造体が配列をメンバーとして持っている場合、その配列はどのようにコピーされるのか?」という点です。 結論から述べると、配列メンバーはシャローコピー(浅いコピー)ではなく、コンパイラが自動的にディープコピー(深いコピー)を行います。次のプログラムでは、構造体 test が配列メンバー str1[] を持っています。st1 を st2 に代入すると、st2 は配列のまったく
-
C++の連結リストで母音ノードを先頭へ、子音ノードを末尾へ並べ替える方法
はじめにこの記事では、連結リスト(リンクリスト)に格納された文字ノードを、母音(A・E・I・O・U)のノードは先頭側へ、子音のノードは末尾側へと並べ替える手法を解説します。ポイントは、並べ替え後も元の相対的な順序が崩れないという点です。入力:A-M-A-Z-O-N出力:A-A-O-M-Z-N計算量:時間 O(N)/空間 O(1)アルゴリズムの考え方母音用と子音用にそれぞれダミーノード(番兵)を用意し、元のリストを先頭から順に走査します。各ノードの文字が母音であれば母音用ダミーノードの直後に、子音であれば子音用ダミーノードの直後に挿入していきます。全ノードの振り分けが完了したら、母音リストの末尾
-
C++で指定位置に開き括弧を含むバランスの取れた括弧式の数を数えるアルゴリズム
問題の概要整数 m と位置情報の配列 position[](1 ≤ length(position[]) ≤ 2m)が与えられたとき、長さ 2m の正しい(バランスの取れた)括弧式を作る方法が何通りあるかを求めます。ただし、指定された位置には必ず開き括弧「[」を置く必要があります。注意:position[] 配列は1始まりのインデックスで表現されます。例えば [0, 1, 1, 0] のように与えられ、「1」は開き括弧を置かなければならない位置を示します。「0」の位置には、開き括弧または閉じ括弧のどちらでも置くことができます。入出力例入力: n = 2, position[] = [1, 0,
-
C++で解くビンパッキング問題:使用するビン(容器)の数を最小化するアルゴリズム徹底解説
異なる重みを持つ m 個の要素と、容量 C のビン(容器)が与えられたとき、すべての要素をビンに割り当て、使用するビンの総数を最小限に抑えることを目指します。ここでは、すべての要素の重みがビンの容量以下であると仮定します。この問題は「ビンパッキング問題」と呼ばれ、NP困難な組合せ最適化問題の一つです。そのため、実用的には近似アルゴリズムを用いて良好な解を高速に求めるアプローチが一般的です。応用例複数のディスクへのデータ配置トラックなどコンテナへの積み込みラジオ・テレビ局の固定長スポット枠への広告詰め込みジョブスケジューリング例入力: weight[] = {4, 1, 8, 1, 4, 2}
-
C++で学ぶバイナリインデックスツリー(フェンウィック木)の仕組みと実装
競技プログラミングやアルゴリズム設計の現場で頻繁に活用されるデータ構造に、バイナリインデックスツリー(Binary Indexed Tree、通称フェンウィック木)があります。本記事では、その基本的な考え方から、実際のC言語・C++による実装例までをわかりやすく解説します。なぜフェンウィック木が必要なのか?単純な数値の配列と比較すると、フェンウィック木は「要素の更新」と「接頭辞和(プレフィックスサム)の計算」という2つの操作のバランスを大きく改善できる点が魅力です。長さ m の通常の配列を考えた場合、選択肢は次の2つしかありません。配列そのものを保持する場合: 要素の更新は定数時間 O(1)
-
C++のSTL setを使って二分木を二分探索木(BST)へ変換する方法
与えられた二分木を、元の木の構造をそのまま保ったまま二分探索木(BST:Binary Search Tree)へ変換する方法を解説します。 この解法では、配列を使う従来の手法の代わりに、C++ STL(Standard Template Library)の set コンテナを活用します。 変換例 例1 入力 11 / \ 3
-
C++で学ぶ二項ヒープ(Binomial Heap)の基礎と操作
二項ヒープ(Binomial Heap)とは、二分ヒープ(Binary Heap)を拡張したデータ構造です。二分ヒープが提供する各種操作に加えて、より高速なマージ(union)操作を実現できる点が大きな特徴です。二項ヒープは、複数の二項木(Binomial Tree)のコレクションとして表現されます。二項木(Binomial Tree)とは?次数kの二項木は、次数k-1の二項木を2つ用意し、一方をもう一方の最左の子として連結することで構築できます。次数kの二項木には、以下のような性質があります。ノードの総数は正確に2k個である。木の深さはkである。深さi(i = 0, 1, ..., k)には
-
【C++】文字列をジグザグ変換するアルゴリズムと実装例
ジグザグ変換とは? 文字列「IWANTTOLEARNCODE」を、指定された行数(n 行)に対してジグザグ状に配置することを考えてみましょう。3 行の場合、パターンは次のようになります。 ITEC WNTLANOE AORD この配置を行ごとに上から順に読み上げると、「ITECWNTLANOEAORD」という文字列が得られます。 つまり今回は、元の文字列と行数を受け取り、この変換処理を実行するモジュール(関数)を作成することが目標となります。 解法のステップ この問題は、次の手順に従って解くことができます。 n = 1 の場合は、変換の必要がないためそのまま s を返します。 サイズ
-
C++で文字列を整数に変換する方法(atoiの実装)
文字列を整数に変換する関数(atoi)を実装する問題を考えてみましょう。このモジュールは、まず不要な空白文字をすべて読み飛ばし、最初の空白以外の文字に到達するまで処理を進めます。その文字から開始して、任意の符号(プラスまたはマイナス)と、それに続くできるだけ多くの数字を読み取り、それらを数値として解釈します。文字列内の最初の空白以外の文字の並びが有効な整数ではない場合、あるいは文字列が空であるか空白のみを含むためにそのような並びが存在しない場合は、変換は行われません。例えば、入力が「-45」であれば、出力は -45 になります。解決のアプローチこの問題を解くには、以下の手順に従います。変数を初
-
C++のdeque::crbegin()の使い方を徹底解説
本記事では、C++におけるdeque::crbegin()の動作と使い方について詳しく解説します。deque(デック)は「double ended queue(両端キュー)」と呼ばれるコンテナで、先頭(front)と末尾(back)の両端において高速な挿入・削除が可能です。これは、末尾(back)のみで高速な挿入を行えるvectorとは対照的な特徴です。さらに、dequeは要素へのランダムアクセスにも対応しています。insert()を使えば途中の位置に要素を挿入することも可能ですが、その場合のパフォーマンスはvectorと同様にあまり良くない点には注意が必要です。deque::crbegin(
-
C++におけるdeque::cbegin()関数の使い方を徹底解説
本記事では、C++ STLにおける deque::cbegin() の動作と使い方について詳しく解説します。 deque::cbegin() 関数とは? deque::cbegin() は、<deque> ヘッダーファイルに含まれる関数の一つで、dequeコンテナの最初の要素を指すイテレータを返します。 注意: cbegin() 関数には引数は一切ありません。 構文 deq.cbegin(); ここで deq は deque オブジェクトを表します。 戻り値 この関数は const_iterator を返します。 const_iterator はランダムアクセスイテレータの一種で、
-
C++のisupper()とislower()関数の使い方と応用例を徹底解説
C++のisupper()とislower()は、ヘッダーファイル「ctype.h」に定義されている組み込み関数です。これらの関数を使うことで、指定した文字や文字列が大文字か小文字かを簡単に判定できます。 isupper()とは? isupper()は、指定された文字列の中に大文字が含まれているかどうかをチェックする関数です。また、1文字だけを入力として渡した場合は、その文字自体が大文字であるかどうかを判定します。 構文 int isupper(int arg); 説明 この関数の戻り値の型はint型です。判定対象の文字列に大文字が含まれる場合は0以外の値(真)を返し、含まれない場合は0(偽)
-
C/C++で大きい方の値のアドレスを返す関数ポインタの宣言方法を解説
この記事では、2つの整数値を比較し、大きい方の値が格納されているメモリアドレスをポインタで返すC/C++関数の作成方法を解説します。関数ポインタを利用すると、実行時に異なる関数のアドレスを渡すことができ、プログラムの柔軟性と抽象性が大きく向上します。実行時の値に基づいて実行する関数を動的に選択できるため、コードをシンプルで保守しやすいものにすることも可能です。big()関数の仕組みこのプログラムでは、2つの整数を参照渡しでbig()関数に渡します。big()関数は受け取った2つの整数値を比較し、大きい方の値のメモリアドレスを返します。戻り値は整数型のポインタであり、その値はゼロまたは非ゼロのい
-
C++ STLのiswblank()関数とは?構文・戻り値・サンプルコードを徹底解説
C++のiswblank()関数は、指定されたワイド文字(wide character)が空白文字(ブランク)であるかどうかを判定するための関数です。C言語では「ctype.h」ヘッダーファイルに、C++標準テンプレートライブラリ(STL)では「cctype」ヘッダーファイルに定義されています。 iswblank()関数の構文 int iswblank(wint_t ch) 戻り値: 引数に渡された文字が空白文字であれば0以外の値を返し、空白文字でなければ0を返します。 パラメータ: ch ― 空白文字かどうかを判定する対象の文字です。 使用例 入力: string str = I Love
-
【C++】ターゲットに最も近い3つの数の合計を求めるアルゴリズム
問題の概要n個の整数を含む配列 nums と、1つのターゲット値 target が与えられます。この中から3つの整数を選び、その合計がターゲットに最も近くなるような組み合わせを見つけ、その合計値を返すことが目的です。なお、各入力には必ず解が1つだけ存在すると仮定してよいものとします。例えば、配列が [-1, 2, 1, -4]、ターゲットが 1 の場合、最適な組み合わせは [-1, 2, 1] で、その合計は 2 となります。これがターゲットに最も近い合計値です。解法のアプローチこの問題は、配列をソートした上で「双方向ポインタ(Two Pointers)」というテクニックを使うことで効率的に解
-
C++ STLのiswcntrl()関数とは?構文・使い方・サンプルコードを解説
C++標準テンプレートライブラリ(STL)に含まれるiswcntrl()関数は、指定されたワイド文字が制御文字であるかどうかを判定するための関数です。制御文字とは、C/C++において画面上の表示位置(印字位置)を占有しない特殊な文字のことを指します。たとえば改行文字(\n)などがこれに該当します。iswcntrl()関数は、cwctypeヘッダーファイル内で定義されています。 iswcntrl()関数の構文 int iswcntrl (wint_t c) パラメータ− c − 制御文字かどうかを判定したい対象の文字を指定します。 戻り値− 引数cが制御文字である場合は0以外の値(非ゼロ)を返