-
C++で数独の有効性を判定するアルゴリズムを解説
9×9の行列で表される数独(Sudoku)が与えられたとします。この課題の目的は、与えられた数独の配置が有効かどうかを判定することです。一般的な数独の盤面は次のようになります。数独のルール各行には1〜9の範囲の数字が入る各列には1〜9の範囲の数字が入る各3×3のブロックには重複のない数字が入る同じ行に同じ数字が現れることはできない同じ列に同じ数字が現れることはできない入出力の例入力例:sudoku[]= [[3,5,.,.,2,.,.,.,.] ,[7,.,.,1,6,5,.,.,.] ,[.,9,8,.,.,.,.,6,.] ,[8,.,.,.,6,.,.,.
-
C++の正規表現(Regex)パターンでIPv4アドレスを検証する方法
IPアドレスが与えられたとき、そのアドレスが有効なIPv4アドレスであるかどうかを正規表現(Regex)を使って検証するのが本記事の目的です。検証の結果、有効なIPv4アドレスであれば「IPv4」と出力し、そうでなければ「Not」と出力します。 有効なIPv4アドレスとは 有効なIPv4アドレスは「X1.X2.X3.X4」という形式で表され、各フィールドXiは0以上255以下の整数である必要があります。また、各フィールドには先頭に余分なゼロ(leading zeros)を含めてはいけません。例えば「192.168.1.1」や「192.168.1.0」は有効なIPv4アドレスですが、「192.
-
C++の正規表現(Regex)パターンでIPv6アドレスを検証する方法
IPアドレスが与えられたとき、正規表現(Regex)を利用して、そのアドレスが有効なIPv6アドレスかどうかを検証することを考えます。検証の結果、有効なIPv6アドレスであれば「IPv6 Address」を、そうでなければ「Not」を出力します。有効なIPv6アドレスとは、「XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX」という形式で表されるIPアドレスのことです。ここで各「X」は16進数の1桁(0〜9、a〜f、A〜F)を表し、合計8つのフィールドがコロン(:)で区切られています。入力例1IP = 3001:0da8:82a3:0:0:8B2E:0270出力No
-
デラノイ数とは?C++でデラノイ数を求めるプログラムの作成方法
デラノイ数(Delannoy Number)とはデラノイ数 D とは、長方形のグリッド上において、南西の角 (0,0) から北東の角 (a,b) まで移動する経路の総数を表す数です。ただし、移動に使用できるのは以下の3種類のステップのみとします。東方向への移動(→)北東方向への移動(↗)北方向への移動(↑)この定義から、デラノイ数は次の漸化式で表すことができます。D(a,b) = D(a-1, b) + D(a, b-1) + D(a-1, b-1) ※ただし D(0,0) = 1例えば、デラノイ数 D(3,3) の値は 63 になります。デラノイ数を求めるアルゴリズムデラノイ数を計算する手順
-
C++で実装するティムソート(Timsort)アルゴリズム:仕組みとコード例
ティムソート(Timsort)は、マージソートと挿入ソートの考え方を組み合わせた安定なソートアルゴリズムです。両者を融合させたハイブリッド型アルゴリズムとも呼ばれ、JavaやPython、C、C++など多くの言語の標準ソート機能に採用されています。基本的な発想は、まず小さな塊をそれぞれ挿入ソートで整列し、その後マージソートのマージ処理を使って塊同士を統合していくというものです。 動作原理 ティムソートでは、配列を小さな塊に分割します。この塊は「RUN」と呼ばれます。各RUNは挿入ソートの手法で整列され、すべてのRUNが整列し終えた後、マージ関数によって順次統合されていきます。 配列のサイズがR
-
C++で二分木の傾斜(Tilt)を求めるアルゴリズムと実装方法
二分木の傾斜とは?二分木の根ノードが与えられたとき、すべてのノードの傾斜(tilt)の合計を求めて返すことを考えます。二分木の傾斜とは、木の各ノードについて「左部分木に含まれるノード値の合計」と「右部分木に含まれるノード値の合計」の絶対差を計算して得られる値です。子ノードを持たないノード(葉ノード)については、左右どちらの部分木も存在しないため、その傾斜は0として扱います。具体例入力:出力:15与えられた二分木の各ノードにおける傾斜を求めると、以下のようになります。ノード3の傾斜 = 0(葉ノードのため)ノード5の傾斜 = 0(葉ノードのため)ノード7の傾斜 = 0(葉ノードのため)ノード2の
-
C++でマトリックスを幅優先探索(BFS)して最短距離を求める方法
2次元マトリックス(行列)上の各セルには、左・右・下・上という4つの方向が存在します。幅優先探索(Breadth First Search、BFS)とは、与えられた2次元行列の中で2つの要素間の最短距離を見つけるためのアルゴリズムです。各セルでは4方向への移動が考えられ、行列内のセルの状態は以下の4つの数値で表現されます。「2」 … そのセルがスタート地点(Source)であることを示します。「3」 … そのセルがゴール地点(Destination)であることを示します。「1」 … そのセルは任意の方向へ移動可能であることを示します。「0」 … そのセルはどの方向にも移動できないことを示します
-
C++で二分木が同型(アイソモーフィック)かどうかを判定する方法
二分木では、各ノードが「左の子」と「右の子」という2つの子ノードを持ちます。ここでは、2つの二分木が与えられたとき、一方の木を左右反転(フリップ)することでもう一方の木が得られるかどうかを判定する問題を解説します。一方の木を反転することでもう一方の木と同じ構造が得られる場合、その2つの木は「同型(アイソモーフィック)」であると定義されます。具体例入力1出力Isomorphic(同型)説明:Tree-2はTree-1を左右反転することで得られるため、この2つの木は同型です。解き方のアプローチこの問題は再帰的なアプローチで効率的に解くことができます。ブール型の関数を用意し、両方の木のルートノードを
-
C++で配列が「ソート済みかつ回転」されているか判定する方法
整数の配列が与えられたとき、その配列が昇順にソートされた状態から、ある位置で回転(ローテーション)されているかどうかを判定するのが本記事のテーマです。 問題の例 入力1: N = [7, 8, 9, 4, 5, 6] 出力: True 解説: 配列は昇順に並んでおり、3番目の位置を境に要素が回転しているため、この場合は True を返します。 入力2: N = [1, 5, 7, 6, 2, 3] 出力: False 解説: 配列は昇順にも並んでおらず、特定の位置での回転も行われていないため、出力は False になります。 解き方のアプローチ 配列の要素は昇順に並んでいるか、あるいはバラバ
-
与えられた二分木が満二分木(Full Binary Tree)かどうかを判定するC++プログラム
二分木が与えられたとき、それが満二分木(Full Binary Tree)であるかどうかを判定するのが本記事のテーマです。すべてのノードが子を0個または2個持つとき、その二分木は満二分木と呼ばれます。 入力例と出力例 入力1: 出力: 1 説明: 葉ノード以外のすべてのノードが2つの子を持っているため、この二分木は満二分木です。 入力2: 出力: 0 説明: ノード2が子を1つしか持っていないため、この二分木は満二分木ではありません。 問題を解くためのアプローチ 与えられた二分木が満二分木かどうかを判定するには、左部分木と右部分木に対して再帰的にチェックを行うのが効果的です。 ノードと
-
C++で指定された数値の最小の桁を見つけるプログラムの書き方
負でない整数が与えられたとき、その数値を構成する各桁の中から最小の数字を見つけるのが本記事の課題です。 例 入力: N = 154870 出力: 0 説明: 入力された数値「154870」には 1・5・4・8・7・0 の6つの桁が含まれており、その中で最も小さいのは「0」です。 解き方のアプローチ この問題を解く最もシンプルな方法は、剰余演算(% 演算子)を使って末尾の桁を1つずつ取り出しながら数値を走査し、取り出した桁が現在の最小値より小さければ最小値を更新していくというものです。 整数 n を入力として受け取ります。 関数 smallest_digit(int n) は引数 n を受け取
-
【C++】サークルソート(Circle Sort)の仕組みと実装方法を徹底解説
サークルソート(Circle Sort)とはサークルソートは、与えられた配列の要素を並べ替えるためのユニークなソートアルゴリズムの一つです。最大の特徴は、配列の先頭と末尾のように「直径上で対になる位置」にある要素同士を比較・交換していく点にあります。片側の部分が整列すると、今度は配列を半分に分割しながら、もう一方の端も同じ要領で再帰的に整列させていきます。サークルソートの動作例ここでは、6つの要素を持つ配列を使って、サークルソートの流れを視覚的に確認してみましょう。入力:N = 6arr[ ] = { 2, 1, 5, 8, 7, 9 }各配列要素を同心円上に配置して描くと、次のようなイメージ
-
C++でランダムポインタを持つリンクリストをディープコピーする方法
ランダムポインタを持つリンクリストとはリンクリスト(連結リスト)は代表的な線形データ構造の一つで、各ノードは「ノードが保持する値(データ)」と「次のノードのアドレスを格納するポインタ(next)」という2つの部分で構成されます。本記事では、さらに各ノードがリスト内の別のノードを指す「ランダムポインタ(random)」を持つリンクリストを扱います。このようなリストに対して、元のリストと同じデータ・同じランダムポインタ構造を持つ新しいリストを作成することを、リンクリストの「ディープコピー(Deep Copy)」と呼びます。例入力:出力:5-> 2 -> 3 -> 7 ->4
-
C++で解く「毎日の気温」問題:スタックを使って次に暖かい日までの日数を効率的に計算する方法
問題の概要正の気温を表す配列 T が与えられているとします。この課題では、リスト内の各気温について、「次により暖かい気温が現れるまでの日数」を計算します。例入力: T = [73, 74, 75, 71, 69, 72, 76, 73]出力: [1, 1, 4, 2, 1, 1, 0, 0]説明: 気温のリスト [73, 74, 75, 71, 69, 72, 76, 73] の場合、0日目(73度)の次に暖かい日は1日目(74度)なので、答えは 1 になります。同様に、6日目(76度)はリスト全体で最も暖かいため、それ以降に暖かい日は存在せず 0 となります。したがって、最終的な出力は [1
-
C++で32ビット符号なし2進数のセットビット(1の個数)を数える方法
32ビットの符号なし2進数が与えられたとき、その中に含まれる「セットビット」、つまり「1」が何個あるかを数えるのが本記事のテーマです。問題の例入力:N = 00000000000000100111出力:4説明: 与えられた符号なし2進数に含まれるセットビット(1)の合計は4個です。したがって、答えとして「4」を返します。解き方のアプローチこの問題は、与えられた32ビットの符号なし2進数の中に「1」がいくつ現れるかを数えるものです。C++では、ビット数を数えるための便利な手段が標準およびコンパイラ拡張として用意されています。代表的な方法は次の2つです。std::bitset の count()
-
【C++】文字列内の各文字から指定した文字までの最短距離を求める方法
文字列 a と特定の文字 char が与えられたとき、文字列内の各文字から char までの距離を出力するのが本記事のテーマです。出力する距離配列のサイズは元の文字列と同じになります。これは、文字列内のすべての文字について、対象となる文字までの距離を求める必要があるためです。 入力例と出力例 例1 a = tutorialspoint char = o 出力: [3, 2, 1, 0, 1, 2, 3, 3, 2, 1, 0, 1, 2, 3] この文字列では「o」はインデックス3とインデックス10の2箇所に存在します。各位置から最も近い「o」までの距離を計算すると、上記のような配列が得られま
-
C++で二分木の左側の葉ノードの合計を求める方法
ルートノードとその左の子・右の子を持つ二分木を考えます。この記事での課題は、親ノードから見て左側の子となっている葉ノード(左葉ノード)の値の合計を求めることです。 例 入力: 出力: 15 説明: 入力された二分木において、親に対して左の子となっている葉ノードは 9、4、2 の3つです。したがって合計は 9+4+2 = 15 となり、出力は 15 になります。 この問題へのアプローチ 二分木が与えられたとき、親に対して左の子となっているすべての葉ノードの合計を求めるのが目的です。 この問題は再帰を使うことで効率的に解けます。基本的な考え方は次のとおりです。まず現在のノードの左の子が存在するか
-
C++で2つの連結リストの交点を見つける方法
連結リストとは連結リスト(Linked List)は線形データ構造の一種です。各ノードは2つの部分で構成されており、一方にはノードの値(データ)が、もう一方には次のノードへのアドレス(ポインタ)が格納されています。ここでは、各ノードがリスト内の他のノードを指すポインタを持つ連結リストを想定します。この問題のタスクは、2つの連結リストが交差するノードを見つけることです。交差していない場合は、NULL(空)を出力として返します。入力例1出力:2解説: 与えられた連結リストは値「2」のノードで交差しているため、「2」を出力として返します。入力例2出力:NULL解説: 共通するノードが存在しないため、
-
C++で2つの文字列をマージして最大の文字列を作成する方法
2つの文字列「a」と「b」、および結果を格納するための文字列「merge」が与えられているとします。この課題は、次のルールに従って「a」と「b」から1文字ずつ取り出し、「merge」を埋めていくことです。 文字列「a」が空でない場合、「a」の先頭の1文字を取り除き、その文字を「merge」に追加します。 文字列「b」が空でない場合、「b」の先頭の1文字を取り除き、その文字を「merge」に追加します。 両方の文字列が空でない場合は、それぞれの残りの文字列を辞書順に比較し、より大きい方の先頭文字を「merge」へ移します。たとえば「a」が「b」より大きい場合は、先に「a」から文字を取り出します
-
【C++】3つの数値をすべてゼロにする最適なステップ数を求めるアルゴリズム
3つの整数が与えられているとします。この課題は、すべての数値を「0」にするために必要な最適な操作回数(ステップ数)を求めることです。 例 入力: a = 4 b = 4 c = 6 出力: 7 解説:すべての数値を0にするまでの最適な手順は以下の通りです。 (4, 4, 6) 1つ目と2つ目の数値から1を引く → (3, 3, 6) 1つ目と3つ目の数値から1を引く → (2, 3, 5) 1つ目と3つ目の数値から1を引く → (1, 3, 4) 1つ目と3つ目の数値から1を引く → (0, 3, 3) 2つ目と3つ目の数値から1を引く → (0, 2, 2) 2つ目と3つ目の数値から1を引