-
C++で各頂点の指定された次数からグラフを生成する方法
頂点のリストと、それぞれの頂点に割り当てられた次数(degree)が与えられたとき、その次数列から無向グラフを生成することを考えます。ここで生成するグラフには、自己ループや多重辺は含まれないものとします。例えば、次数列が [2, 2, 1, 1] の場合、生成できるグラフは次の図のようになります。アルゴリズムの手順この問題は、貪欲法(グリーディ法)の考え方を使って解くことができます。具体的な手順は以下の通りです。グラフの構造を保存するための隣接行列 adj を定義し、すべての要素を 0 で初期化します。各頂点 i について、それより後ろの頂点 j を順に調べます。頂点 i と頂点 j の次数が
-
L = {aⁱbʲcᵏ | i × j = k、i, j, k ≥ 1} を受理するチューリングマシンの構築方法
本記事では、言語 L = {aⁱbʲcᵏ | i × j = k、i, j, k ≥ 1} に対応するチューリングマシンの構築方法を解説します。この言語は、A・B・C の3種類の記号のみからなる文字列のうち、「A の個数(i)と B の個数(j)の積が C の個数(k)と一致する」という条件を満たすものの集合を表しています。 受理される文字列の例 例えば、w = AABBBBCCCCCCCC という入力文字列を考えてみましょう。この場合、A が2個、B が4個、C が8個含まれており、2 × 4 = 8 という関係が成立しているため、このチューリングマシンはこの文字列を受理します。 構築のアプ
-
L = {AⁱBʲCᵏ | i < j < k、i ≥ 1} を認識するチューリングマシンの構築方法
ここでは、言語 L = {AⁱBʲCᵏ | i < j < k、i ≥ 1} を認識するチューリングマシンの構築方法を解説します。この言語は A・B・C の 3 種類の記号のみで構成される文字列を扱い、B の個数が A の個数より厳密に多く、さらに C の個数が B の個数より厳密に多いことが条件となります。w は入力文字列を表します。たとえば w = AABBBBCCCCC の場合、A が 2 個・B が 4 個・C が 5 個であり、2 < 4 < 5 という条件を満たすため、このチューリングマシンは文字列を受け入れます。解法のアプローチこの問題を解く基本的な考え方
-
L = {aⁱbʲcᵏ | i > j > k、k ≥ 1} を認識するチューリングマシンの構築方法
この記事では、言語 L = {aibjck | i > j > k、k ≥ 1} を認識するチューリングマシンの構築方法を解説します。この言語は、記号 a、b、c のみから構成される文字列のうち、「a の個数が b の個数より多く、さらに b の個数が c の個数より多い」という条件を満たすものの集合を表します。 言語の定義と具体例 例えば、w = aaaaaabbbbccc(a が 6 個、b が 4 個、c が 3 個)という入力文字列は、6 > 4 > 3 ≥ 1 という条件を満たしているため、このチューリングマシンによって受理されます。 一方で、a と b の個
-
言語 L = {0ⁿ1ⁿ2ⁿ | n ≥ 1} を認識するチューリングマシンの構築方法
本記事では、言語 L = {0ⁿ1ⁿ2ⁿ | n ≥ 1} を認識するチューリングマシンの構築方法について解説します。この言語は、記号「0」「1」「2」の3種類のみで構成され、それぞれの記号が同じ個数ずつ順番に並んだ文字列の集合を表します。例えば、w = 000111222 のような文字列は、0・1・2がそれぞれ3個ずつ対応しているため、チューリングマシンによって受理されます。 解法のアプローチ この問題を解くには、先頭から順に記号を別の記号へ置き換えていく「マーキング方式」を採用します。具体的な手順は以下の通りです。 まず、先頭の「0」を1つ選んで「x」に置き換えます。 次に、右方向へヘ
-
言語 L = {ww | w ∈ {0,1}} を認識するチューリングマシンの構築方法
言語 L = {ww | w ∈ {0,1}} とはここでは、言語 L = {ww | w ∈ {0,1}} を認識するチューリングマシンの構築方法を解説します。この言語は、記号 0 と 1 のみから構成される文字列 w が2回繰り返された形(ww)の集合を表しています。例えば、w = 10110 の場合、チューリングマシンが受理すべき文字列は z = 1011010110 となります。解法のアプローチステップ1:文字列の中点を見つけるまず最初の目標は、文字列の中点を特定することです。そのために、左端の記号(0 なら x、1 なら y)と右端の記号(0 なら x、1 なら y)を順次変換しなが
-
言語 L = {ww^r | w ∈ {0,1}} を受理するチューリングマシンの構築方法
ここでは、言語 L = {wwr | w ∈ {0, 1}} を受理するチューリングマシンの構築方法について解説します。この言語は、文字「0」と「1」のみで構成される文字列を扱うものです。w は任意の文字列を表し、wr はその逆順(反転)の文字列を意味します。 例えば、w = 10110 の場合、wr は 01101 となります。したがって、このチューリングマシンが受理すべき文字列 z は、10110 と 01101 を連結した z = 1011001101 になります。 解法のアプローチ この問題を解くためには、以下の手順に従います。 先頭の記号を確認する: 文字列の最初の記号を読み取りま
-
先行順走査(プレオーダー)の結果から二分探索木(BST)を構築する ― C++による実装
ある先行順(プレオーダー)走査の結果が与えられているとします。この走査結果をもとに、元の二分探索木(BST)を復元することを考えましょう。例えば、走査結果が [10, 5, 1, 7, 40, 50] である場合、構築される木は次の図のようになります。 解法のアプローチ:範囲制約を利用する この問題を効率的に解く鍵となるのは、各ノードに対して「取り得る値の範囲 {min … max}」を設定することです。具体的な手順は以下の通りです。 まず、範囲を {INT_MIN … INT_MAX} として初期化します。 最初の要素は必ずこの範囲内に収まるため、その値でルートノードを作成します。 左
-
前順走行(プレオーダー)から二分探索木(BST)を構築する方法 ― C++実装解説
二分探索木(BST)の前順走行(プレオーダートラバーサル)の結果が与えられたとします。この走行結果をもとに、元の木を復元する必要があります。例えば、前順走行が [10, 5, 1, 7, 40, 50] の場合、構築される木は次のようになります。アルゴリズムの考え方この問題は、スタックを1つ利用することで線形時間で解くことができます。BSTの性質と前順走行の特徴を組み合わせるのがポイントです。具体的な手順は以下のとおりです。空のスタックを作成します。最初の値を根(ルート)ノードとし、スタックにプッシュします。スタックが空でなく、かつ次の値がスタックのトップ要素より大きい間はポップを続けます。最
-
C++でレベル順走査の結果から二分探索木(BST)を構築する方法
レベル順走査(レベル順序トラバーサル)の結果が与えられたとします。この走査結果をもとに、二分探索木(BST:Binary Search Tree)を構築する必要があります。例えば、走査結果が [7, 4, 12, 3, 6, 8, 1, 5, 10] の場合、構築される木は以下の図のようになります。この問題を解くには、再帰的なアプローチを使用します。レベル順走査の性質上、最初の要素がルートとなり、その後の要素はBSTの条件(左の子は親以下、右の子は親より大きい)に従って順番に挿入されていきます。具体的には、以下の手順で構築を進めます。まず、配列の最初の要素を取り出し、これを木のルートとします。
-
C++で二分木を論理AND特性を保持する木に変換する方法
はじめに このチュートリアルでは、与えられた二分木を「論理AND特性」を満たす木へ変換するプログラムをC++で実装する方法を解説します。 ここで扱う問題は次のとおりです。各ノードの値が 0 または 1 のいずれかである二分木が与えられたとき、すべての内部ノードの値を「左の子の値と右の子の値の論理AND演算の結果」に書き換えます。これにより、木全体が論理AND特性を保持するようになります。なお、葉ノードの値はそのまま変更しません。 アルゴリズムの考え方 変換には、葉に近いノードから順に処理する「後順(帰りがけ順)の再帰走査」を利用します。具体的な手順は以下のとおりです。 まず、左部分木を再帰的
-
C++で二分木を双方向リンクリストに変換する方法(セット1)
はじめに このチュートリアルでは、二分木(バイナリツリー)を双方向リンクリスト(ダブリーリンクリスト)に変換するC++プログラムについて解説します。 変換対象の二分木が与えられ、それを双方向リンクリストへ変換するのが課題です。具体的には、二分木の各ノードが持つ左ポインタ(left)と右ポインタ(right)を、リンクリストの前ポインタ(prev)と次ポインタ(next)としてそのまま再利用します。さらに、変換後のリンクリストのノードの並び順は、元の二分木の通り順(中順・inorder)トラバーサルと一致していなければなりません。 アプローチ この問題には非常にシンプルな手法が使えます。二分木を
-
C++で二分木を双方向連結リストに変換する方法(セット2)
はじめにこのチュートリアルでは、C++を使って二分木を双方向連結リスト(Doubly Linked List)に変換するプログラムについて解説します。入力として二分木が与えられ、それを双方向連結リストへ変換するのが課題です。変換の際には、木の左ポインタと右ポインタを、それぞれリストの前ポインタ(prev)と次ポインタ(next)として再利用します。また、変換後のリストの並び順は、元の二分木を中間順走査(inorder traversal)した順序と一致していなければなりません。アルゴリズムの考え方ここでは、少し異なるアプローチを採用します。二分木を逆中間順(右部分木 → 根 → 左部分木)で走
-
C++で通常のBSTを平衡BST(平衡二分探索木)に変換する方法
この記事では、C++を使って通常の二分探索木(BST)を平衡二分探索木(Balanced BST)に変換するプログラムについて詳しく解説します。 ここでは、左または右に偏った(スキューした)二分探索木が与えられることを想定します。偏ったBSTは、実質的に連結リストと同じ状態になり、検索・挿入・削除の計算量が O(n) まで悪化してしまいます。これを一定の手順に従って平衡な形に変換することで、計算量を O(log n) に戻すことができます。 変換の基本的な考え方 偏ったBSTを平衡BSTに変換するには、以下の2段階の手順を用います。 中順走査(Inorder Traversal)でノードを
-
C++で数値を負の基数表現に変換する方法
はじめにこの記事では、与えられた数値を負の基数(ネガティブベース)表現に変換するC++プログラムについて解説します。具体的には、ある整数と対応する負の基数が入力として与えられ、その数値を負の基数による等価な表現へと変換します。ここで扱う負の基数は、-2 から -10 までの範囲に限定します。負の基数変換の仕組み通常の進数変換と同様に、「数値を基数で割った余り」を下位の桁から順に並べることで変換を行います。ただし、負の基数で除算すると余りが負になる場合があるため、その際は次のように調整します。余りに -negBase を加算し、余りを 0 以上の値に修正する同時に商に 1 を加算し、計算の整合性
-
C++で最小回数の操作によって数値mをnに変換する方法
このチュートリアルでは、指定された操作を最小回数だけ使って、ある数値 m を別の数値 n に変換するプログラムについて解説します。 2つの整数 m と n が与えられ、許可された操作のみを用いて整数 m を n へ変換するとき、その操作回数をできるだけ少なくすることを目指します。 許可される操作 与えられた数値に2を掛ける(×2) 与えられた数値から1を引く(−1) アルゴリズムの考え方 この問題は、目標値 n の側から逆算的に考えると効率的に解けます。各ケースでの処理は次の通りです。 m == n の場合: 変換は不要なので 0 を返します。 m > n の場合: 掛け算は数を増
-
【C++】長さNの数字列を、いずれかの1桁がK回以上出現するように変換する方法
はじめに このチュートリアルでは、長さNの数値を変換して、いずれか1つの数字(0〜9)が少なくともK回含まれるようにするプログラムを、C++を用いて解説します。 問題の概要 長さNの数値(数字列)が与えられます。私たちのタスクは、与えられた数値のいくつかの桁を書き換えて、どれか1つの数字が少なくともK回繰り返されるようにすることです。同時に、この操作にかかるコストも計算する必要があります。ここでいうコストとは、元の数字と書き換え後の数字の差の絶対値の合計のことです。最終的に、コストが最小となる変換後の数値と、その最小コストを出力します。 アルゴリズムの考え方 この問題は、目標となる数字を0
-
C++で文章を携帯電話のテンキー入力シーケンスに変換する方法
このチュートリアルでは、与えられた文章(英字の文字列)を、旧式の携帯電話でその文字を入力する際に押すテンキーの数字列へと変換するC++プログラムについて解説します。かつてのフィーチャーフォンでは、各数字キーに複数のアルファベットが割り当てられていました。たとえば「2」にはA・B・C、「3」にはD・E・Fが対応しており、目的の文字を入力するには対応するキーを必要な回数だけ押す仕組みでした。キーとアルファベットの対応表2 → A, B, C3 → D, E, F4 → G, H, I5 → J, K, L6 → M, N, O7 → P, Q, R, S8 → T, U, V9 → W, X, Y
-
C++で文字列を文字の正方行列グリッドに変換する方法
このチュートリアルでは、文字列を文字の正方行列グリッドに変換するプログラムの作成方法について解説します。具体的には、文字の並びからなる文字列が与えられ、その文字列を指定した行数と列数を持つ行列グリッドの形式で出力することが課題となります。アルゴリズムの考え方文字列の長さを l とすると、グリッドの行数と列数は次のように決定できます。行数 = floor(√l)(平方根の切り捨て)列数 = ceil(√l)(平方根の切り上げ)行数と列数の積が文字列の長さに満たない場合は、行数を列数と同じ値に設定し、すべての文字がグリッドに収まるように調整します。サンプルコード#include <bits/
-
C++で文字列を16進数のASCII値に変換する方法
このチュートリアルでは、C言語スタイルのコードを用いて、文字列を16進数のASCII値に変換するプログラムについて解説します。変換の対象となるのは、任意の文字の並びからなる文字列です。私たちのタスクは、与えられた文字列を1文字ずつ対応する16進数表現に置き換え、その結果を出力することです。変換の仕組みコンピュータ内部では、各文字はASCIIコードと呼ばれる整数値として扱われています。たとえば、英小文字「t」のASCIIコードは10進数で116ですが、これを16進数に変換すると「74」になります。この処理を文字列の終端を示すヌル文字(\0)に到達するまで繰り返すことで、文字列全体を16進数表記へ