!^
zoxDB6r^7};#QP;Iv2jW-XHm;j6pYyBEuOvYP7lv(yxd*4Q9#F8Z@EP;gv+W^AoyBx
zkO4Pz%TI~Zl&m0eu3G2D=a|uwt1shCJn~fT98JLX@9H?{qhsNbgELyspbKQ9nI&YD
zENBZB1oR4dAGA3Oxt$K8DM7eB!*`XpR27YnR|Uh+EPPL>;HNl|RU|x{TcP_4onNT?
z9sK_F(4p|`6(6w>YxPIZq&wTZgCHp3UtMYZWp=
zguqLl*ehUAs*iME2hFdc?Iw6o2}U6k0IMvG862p^whk5qky?YBOi%*|`EG7L5HVaz
zZo(Y2@$jlxUKS0vV>ycx83{1FQpFGw|o`c&S{$#^{D}3$LyGKJ2G33yS(tG93}+
zi6XXO-g9s};V|n;be7hL1{U#b7jFN`)q1bgF+*AJlRCLM)j@_-x+nSKq48AMPOaS
zYf-QpYf+x<<*^z3vOqm9XuYG+HG86Yi0ooF@xIac{kQTg`LN0&v^_A+geG(Lr&XGn
zFCmhiuX?L(bX?Gmscwv8hb@hE(iX&Pgq(^&*uRKg+C_!c55zudyrI32)EC_LAWV*v*Gi7Lv`;%n)kSKP9+OPBBo7I$K
z!qR8yk}Rzhh0?K#PYa;|;^U`^4ve|uZOHmAzL2Q1Fpb!XScGw*u^@@<(D2QQw!@pV
z%8lEzS0K74lJ14jgkz;=EPnx;B4U!d+^(fv%^KJk?xvo0o$ys?-R&9py$ajH_w#dHQbakwB`F&kmv`&B`ViI%kh-A1|}
zfWK5t+DeG)UD3GIBQg03)Wr2qBf06#x7jP_MOPT5+1$GPBiZ^MRil-x*2|5-#3^u|
zltG?1q++Bq)J%1`gL?7GTQ0CmD%V1{Jj4E|E1-|o$X*MY!Kd%tT=#7!u4o#%E;
zy&C5Vh&O7mbi_4xXu3z|7s50BpnmT-9^lS-k%iM|eQ6>ThPl!y44*)oA?4U!YX_Az
zN!Gny8Unq!hJIU;kfe4US|>}*IRfsuu=@5Ykpp`>{A25RzYXSwwH?{&!=;pp{VQ)}
zWWe|1`il{%i@3_i;U9Kr$j}kEco^-6s#`BQzGuC!7)Ei%^FbI2rePFcRIz~wyM2S(
z{QcwMch)Ws#Yz{W_=&go@V8GX^(R{PZWy8_OuHDng>!GSlt;LSRaGko`WPpsnbjFB
z$BbCbBGGK_&=h~E!0eUFlkO9h(4|P6Dn~l1v5;)ns%?1=23c@9FKvl)h43Y}fG8q`
z0bFw45_dvfTN}i
zv}H1o2wYw@{eyHj0q-aVH8
zn4ygQqzhtjbsJRXX`Ivus0+IUxpL!D!wRU9
zjEywp`5ZZB?*ySypa?q4%<#jykkP!y(JlRQ
z0-9lf)1hrL_cq&2^n)b~f@>3j$oiGGR!Z8MRPIYhiOvE;PFkv^QPa0R!*a?Je!b8-
z_Q3vxm9iyy?cYm}HzxE*`~}D)3@^1Ck|_wmvp;eyu5*8Qp&ufj$iSib8E(0AtpYZB
zm9ziloR1QtSRU&6XWN+VOvk~(obk;+GizFP{vqOCYpq45(Y0GoNrO@*g)SIs)SwjE
z1#Ox3LM~K?4d9!GvP$Cx^Cqv}#@dPW)rN;<(Ee@~3KiaFHxR=JeE0BJXf70az-}$y
z9N%1TE$?ga-P(YKMK6~7Cj$H63@7pgw>uy|7wS?LU5iWfC8JGtA1
z&-GTV*NAnv#iDt2XchK?E44DugPBSM$=(mHm(KZa}TUQ>0@AMR1zkPLOsTsLg*>K
z0#C~6qev?@V^&sf#b6SL_fW8P*QQcCrwbp&91e^%a1%ENzouwzY=m+nN*gVz-or8~R?g!MALkL&;au2ujra8pgnD3lQ|JwB5`9qp+jH1_fY#W_o
z7y#=ZYL<1zc%%d|%+;v8Ih1DX%s;ME%czpH*%lrElgnv%n%^C~JlEoK!=%DkaN2+P
z!eBJWXr+$%yQpUg+)s)OwPfP56xkh@PssF=Q1_*DI!D52|Ucm`^sN)rCQdQQM;)?+xeJb88Sy
z<7J3c=jN6t{M%e=ZlJQgROGlkv716@5WoFO@DdhN^vs78|*QZC5iBK
zaz|7C9K(s-E95Ra=QjVwSP7ht_E~LAy)sXBoh3WB#Hh$ZsGY4on;z65&xc{Q%}t&o
zu<%t6q1`N+Del?u7InojN-)vWoAymByi?wi6B}%H4?=_mzj=^KyIgRe?T-6YR{F#f
zt{LTtD+65!^6#a#`mt-SA9i`Nnn=oA@I)_rr9pXCND((l&*%@~S`WojA=`Yuz#%LB
z4lX(MYO~^0ac>Yic~8s8h%MQmerBVFs=Fz)T#S9hN}L*~*P-T_Qsd#o?eNszRO-6D
zTQy)8)xwqCESxqETySNbXlOAH0-U+?O@m^x31sEInGc7ivP8yAI}`t~7{$jcelc{fn)RI5&!J?vbLLd`T6gcqDxt
zV!=RV^@zvBlL3P*^dtwT65v=NtV-zV*7IudVH7
zwztcmq01U|Y`fGD3j_D!hE=O%riOq+%K-V#pMkTu0n9V*W|Z=0&Q<}~MUeJljw*w@
zSP4zeP~AMGX6kw1*p=DB>AMxStvxS>%XUpH=JFiGUfy;<5_O-LVyqdOo?)jkvl+a5
zsyD-0(8gRQ3=g;+UO$#abnPIh-k}?_W=-H6InT}W$gQQaRWk?4+<|WXiY6!|`K^($
QrGTi^W>Yjn+TX?h1ytwN^Z)<=
literal 0
HcmV?d00001
diff --git a/en/README.md b/en/README.md
index 8cc894855..39c17bdff 100644
--- a/en/README.md
+++ b/en/README.md
@@ -41,6 +41,8 @@
繁體中文
|
English
+ |
+ 日本語
## The book
diff --git a/ja/CONTRIBUTING.md b/ja/CONTRIBUTING.md
new file mode 100644
index 000000000..ecbac04f4
--- /dev/null
+++ b/ja/CONTRIBUTING.md
@@ -0,0 +1,134 @@
+# 中国語から日本語への貢献ガイドライン
+
+「Hello アルゴリズム」を中国語から日本語に翻訳するにあたり、以下のアプローチを採用しています:
+
+1. **AI翻訳**: 大規模言語モデルを使用して初期翻訳を実施します。
+2. **人による最適化**: 機械生成された出力を手動で改良し、正確性と自然さを確保します。
+3. **プルリクエストレビュー**: 最適化された翻訳は、GitHubのプルリクエストワークフローを通じてレビュアーによって二重チェックされます。
+4. さらなる改善のため、ステップ `2.` と `3.` を繰り返します。
+
+
+
+## 参加方法
+
+以下の基準を満たす貢献者を求めています:
+
+- **技術的背景**: コンピュータサイエンス、特にデータ構造とアルゴリズムに関する強固な基礎知識
+- **言語スキル**: 日本語ネイティブまたは日本語に精通した方、中国語の読解力
+- **利用可能な時間**: オープンソースプロジェクトへの貢献に専念し、長期的な翻訳作業に参加する意欲
+
+つまり、私たちの貢献者は、さまざまな言語背景を持つコンピュータサイエンティスト、エンジニア、学生であり、それぞれの目的には異なる焦点があります:
+
+- **中国語読解力を持つ日本語ネイティブ**: 中国語版と日本語版の間の翻訳の正確性と一貫性を確保する
+- **日本語に精通した中国語話者**: 日本語コンテンツの自然さと流暢さを向上させ、自然で読みやすいものにする
+
+> [!note]
+> 参加にご興味がある方は、お気軽に krahetx@gmail.com またはWeChat `krahets-jyd` までご連絡ください。
+>
+> 進捗管理とタスク割り当てには、この[Notionページ](https://hello-algo.notion.site/chinese-to-english)を使用しています。詳細はこちらをご覧ください。
+
+## 翻訳プロセス
+
+> [!important]
+> 作業を開始する前に、GitHubのプルリクエストワークフローに慣れ、以下の「翻訳基準」と「翻訳のための疑似コード」を必ずお読みください。
+
+1. **タスク割り当て**: Notionワークスペースでタスクを自己割り当てします。
+2. **翻訳**: ローカルPCで翻訳を最適化します。詳細は以下の「翻訳疑似コード」セクションを参照してください。
+3. **ピアレビュー**: プルリクエスト(PR)を提出する前に、変更を慎重にレビューしてください。PRは2名のレビュアーの承認後にメインブランチにマージされます。
+
+## 翻訳基準
+
+> [!tip]
+> **「正確性」と「自然さ」は、主に中国語を理解できる日本語ネイティブスピーカーによって扱われます。**
+>
+> 場合によっては、「正確性(一貫性)」と「自然さ」はトレードオフの関係にあり、一方を最適化すると他方に大きな影響を与える可能性があります。そのような場合は、プルリクエストにコメントを残して議論してください。
+
+**正確性**:
+
+- [用語集](https://www.hello-algo.com/chapter_appendix/terminology/)セクションを参照して、翻訳全体で用語の一貫性を保ちます。
+- 技術的な正確性を優先し、中国語版のトーンとスタイルを維持します。
+- 修正が正確で包括的であることを確保するため、常に中国語版の内容とコンテキストを考慮してください。
+
+**自然さ**:
+
+- 翻訳は日本語の表現慣習に従い、自然で流暢に読めるようにすべきです。
+- 記事を調和させるために、常にコンテンツのコンテキストを考慮してください。
+- 中国語と日本語の文化的な違いに注意してください。例えば、中国語の「拼音」は日本語には存在しません。
+- 最適化された文が元の意味を変える可能性がある場合は、議論のためにコメントを追加してください。
+
+**フォーマット**:
+
+- 図表は展開時に自動的に番号付けされるため、手動で番号を付けないでください。
+- バグ修正を除き、各PRは管理可能なレビューサイズを確保するため、少なくとも1つの完全なドキュメントをカバーすべきです。
+
+**レビュー**:
+
+- レビュー中は、変更の評価を優先し、必要に応じて周囲のコンテキストを参照してください。
+- お互いの視点から学ぶことで、より良い翻訳とより一貫性のある結果につながります。
+
+## 翻訳疑似コード
+
+以下の疑似コードは、典型的な翻訳プロセスのステップをモデル化しています。
+
+```python
+def optimize_translation(markdown_texts, lang_skill):
+ """翻訳を最適化する"""
+ for sentence in markdown_texts:
+ """正確性は主に中国語を理解できる日本語ネイティブスピーカーによって処理される"""
+ if lang_skill is "日本語ネイティブ + 中国語読解力":
+ if is_accurate_Chinese_to_Japanese(sentence):
+ continue
+ # 正確性を最適化
+ result = refine_accuracy(sentence)
+
+ """
+ 自然さは主に日本語ネイティブスピーカーによって処理され、
+ 副次的に中国語話者によって処理される
+ """
+ if is_authentic_Japanese(sentence):
+ continue
+ # 自然さを最適化
+ result = refine_authenticity(sentence)
+ # 一貫性を損なう可能性がある場合はPRにコメントを追加
+ if break_consistency(result):
+ add_comment(description)
+
+ pull_request = submit_pull_request(markdown_texts)
+ # PRは2名以上のレビュアーによる承認後にマージされる
+ while count_approvals(pull_request) < 2:
+ continue
+ merge(pull_request)
+```
+
+以下はレビュアー向けの疑似コードです:
+
+```python
+def review_pull_requests(pull_request, lang_skill):
+ """PRをレビューする"""
+ # PR内のすべての変更をループ
+ while is_anything_left_to_review(pull_request):
+ change = get_next_change(pull_request)
+
+ """正確性は主に中国語を理解できる日本語ネイティブスピーカーによって処理される"""
+ if lang_skill is "日本語ネイティブ + 中国語読解力":
+ # 中国語版と日本語版の間の正確性(一貫性)をチェック
+ if is_accurate_Chinese_to_Japanese(change):
+ continue
+ # 正確性(一貫性)を最適化
+ result = refine_accuracy(change)
+ # PRにコメントを追加
+ add_comment(result)
+
+ """
+ 自然さは主に日本語ネイティブスピーカーによって処理され、
+ 副次的に中国語話者によって処理される
+ """
+ if is_authentic_Japanese(change):
+ continue
+ # 自然な日本語でない場合は自然さを最適化
+ result = refine_authenticity(change)
+ # PRにコメントを追加
+ add_comment(result)
+
+ approve(pull_request)
+```
\ No newline at end of file
diff --git a/ja/README.md b/ja/README.md
new file mode 100644
index 000000000..f9c2aad2c
--- /dev/null
+++ b/ja/README.md
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+ アニメーションで図解、ワンクリック実行のデータ構造とアルゴリズム入門講座
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 简体中文
+ |
+ 繁體中文
+ |
+ English
+ |
+ 日本語
+
+
+## この本について
+
+このオープンソースプロジェクトは、データ構造とアルゴリズムの無料で初心者向けの入門講座を作成することを目的としています。
+
+- アニメーションによる図解、わかりやすい内容、なめらかな学習曲線により、初心者がデータ構造とアルゴリズムの「知識マップ」を探索できます。
+- ワンクリックでコードを実行でき、読者のプログラミングスキルを向上させ、アルゴリズムの動作原理とデータ構造の基礎となる実装を理解できます。
+- 教えることで学ぶことを促進し、質問や洞察を自由に共有してください。議論を通じて一緒に成長しましょう。
+
+この本が役立つと思われた場合は、スター :star: を付けてサポートしてください。ありがとうございます!
+
+## 推薦の言葉
+
+> 「データ構造とアルゴリズムに関するわかりやすい本で、読者が頭と手を使って学ぶように導きます。アルゴリズム初心者に強くお勧めします!」
+>
+> **—— 鄧俊輝教授、清華大学コンピュータサイエンス技術学部**
+
+> 「データ構造とアルゴリズムを学んでいたときに『Hello Algo』があったなら、10倍簡単だったでしょう!」
+>
+> **—— Mu Li、Amazon シニアプリンシパルサイエンティスト**
+
+## 貢献
+
+> [!Important]
+>
+> 英語から日本語への翻訳への貢献を歓迎します!詳細は[CONTRIBUTING.md](CONTRIBUTING.md)をご覧ください。
+
+このオープンソースブックは継続的に更新されており、読者により良い学習コンテンツを提供するため、このプロジェクトへの参加を歓迎します。
+
+- [内容の修正](https://www.hello-algo.com/ja/chapter_appendix/contribution/): 文法エラー、内容の欠落、曖昧さ、無効なリンク、コードのバグなど、コメントセクションで間違いを修正したり指摘したりしてください。
+- [コードの移植](https://github.com/krahets/hello-algo/issues/15): さまざまなプログラミング言語でのご貢献をお待ちしています。現在、Python、Java、C++、Go、JavaScriptを含む12言語をサポートしています。
+
+貴重なご提案とフィードバックを歓迎します。ご質問がある場合は、Issuesを提出するか、WeChat: `krahets-jyd`でお問い合わせください。
+
+この本のすべての貢献者に感謝を捧げたいと思います。彼らの無私の献身により、この本がより良いものになりました。貢献者の皆様:
+
+
+
+
+
+
+
+## ライセンス
+
+このリポジトリ内のテキスト、コード、画像、写真、動画は[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)の下でライセンスされています。
diff --git a/ja/codes/cpp/chapter_array_and_linkedlist/array.cpp b/ja/codes/cpp/chapter_array_and_linkedlist/array.cpp
new file mode 100644
index 000000000..1bd279f1b
--- /dev/null
+++ b/ja/codes/cpp/chapter_array_and_linkedlist/array.cpp
@@ -0,0 +1,113 @@
+/**
+ * File: array.cpp
+ * Created Time: 2022-11-25
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 要素への乱数アクセス */
+int randomAccess(int *nums, int size) {
+ // [0, size)の範囲で乱数を選択
+ int randomIndex = rand() % size;
+ // 乱数要素を取得して返却
+ int randomNum = nums[randomIndex];
+ return randomNum;
+}
+
+/* 配列長の拡張 */
+int *extend(int *nums, int size, int enlarge) {
+ // 拡張された長さの配列を初期化
+ int *res = new int[size + enlarge];
+ // 元の配列の全要素を新しい配列にコピー
+ for (int i = 0; i < size; i++) {
+ res[i] = nums[i];
+ }
+ // メモリを解放
+ delete[] nums;
+ // 拡張後の新しい配列を返却
+ return res;
+}
+
+/* `index`に要素numを挿入 */
+void insert(int *nums, int size, int num, int index) {
+ // `index`より後のすべての要素を1つ後ろに移動
+ for (int i = size - 1; i > index; i--) {
+ nums[i] = nums[i - 1];
+ }
+ // indexの位置にnumを代入
+ nums[index] = num;
+}
+
+/* `index`の要素を削除 */
+void remove(int *nums, int size, int index) {
+ // `index`より後のすべての要素を1つ前に移動
+ for (int i = index; i < size - 1; i++) {
+ nums[i] = nums[i + 1];
+ }
+}
+
+/* 配列の走査 */
+void traverse(int *nums, int size) {
+ int count = 0;
+ // インデックスによる配列の走査
+ for (int i = 0; i < size; i++) {
+ count += nums[i];
+ }
+}
+
+/* 配列内の指定要素を検索 */
+int find(int *nums, int size, int target) {
+ for (int i = 0; i < size; i++) {
+ if (nums[i] == target)
+ return i;
+ }
+ return -1;
+}
+
+/* ドライバーコード */
+int main() {
+ /* 配列を初期化 */
+ int size = 5;
+ int *arr = new int[size];
+ cout << "Array arr = ";
+ printArray(arr, size);
+
+ int *nums = new int[size]{1, 3, 2, 5, 4};
+ cout << "Array nums = ";
+ printArray(nums, size);
+
+ /* 乱数アクセス */
+ int randomNum = randomAccess(nums, size);
+ cout << "Get a random element from nums = " << randomNum << endl;
+
+ /* 長さの拡張 */
+ int enlarge = 3;
+ nums = extend(nums, size, enlarge);
+ size += enlarge;
+ cout << "Extend the array length to 8, resulting in nums = ";
+ printArray(nums, size);
+
+ /* 要素の挿入 */
+ insert(nums, size, 6, 3);
+ cout << "Insert the number 6 at index 3, resulting in nums = ";
+ printArray(nums, size);
+
+ /* 要素の削除 */
+ remove(nums, size, 2);
+ cout << "Remove the element at index 2, resulting in nums = ";
+ printArray(nums, size);
+
+ /* 配列の走査 */
+ traverse(nums, size);
+
+ /* 要素の検索 */
+ int index = find(nums, size, 3);
+ cout << "Find element 3 in nums, index = " << index << endl;
+
+ // メモリを解放
+ delete[] arr;
+ delete[] nums;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_array_and_linkedlist/linked_list.cpp b/ja/codes/cpp/chapter_array_and_linkedlist/linked_list.cpp
new file mode 100644
index 000000000..f7ad5eb8f
--- /dev/null
+++ b/ja/codes/cpp/chapter_array_and_linkedlist/linked_list.cpp
@@ -0,0 +1,89 @@
+/**
+ * File: linked_list.cpp
+ * Created Time: 2022-11-25
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 連結リストのノードn0の後にノードPを挿入 */
+void insert(ListNode *n0, ListNode *P) {
+ ListNode *n1 = n0->next;
+ P->next = n1;
+ n0->next = P;
+}
+
+/* 連結リストのノードn0の後の最初のノードを削除 */
+void remove(ListNode *n0) {
+ if (n0->next == nullptr)
+ return;
+ // n0 -> P -> n1
+ ListNode *P = n0->next;
+ ListNode *n1 = P->next;
+ n0->next = n1;
+ // メモリを解放
+ delete P;
+}
+
+/* 連結リストの`index`番目のノードにアクセス */
+ListNode *access(ListNode *head, int index) {
+ for (int i = 0; i < index; i++) {
+ if (head == nullptr)
+ return nullptr;
+ head = head->next;
+ }
+ return head;
+}
+
+/* 連結リストで値がtargetの最初のノードを検索 */
+int find(ListNode *head, int target) {
+ int index = 0;
+ while (head != nullptr) {
+ if (head->val == target)
+ return index;
+ head = head->next;
+ index++;
+ }
+ return -1;
+}
+
+/* ドライバーコード */
+int main() {
+ /* 連結リストを初期化 */
+ // 各ノードを初期化
+ ListNode *n0 = new ListNode(1);
+ ListNode *n1 = new ListNode(3);
+ ListNode *n2 = new ListNode(2);
+ ListNode *n3 = new ListNode(5);
+ ListNode *n4 = new ListNode(4);
+ // ノード間の参照を構築
+ n0->next = n1;
+ n1->next = n2;
+ n2->next = n3;
+ n3->next = n4;
+ cout << "The initialized linked list is" << endl;
+ printLinkedList(n0);
+
+ /* ノードを挿入 */
+ insert(n0, new ListNode(0));
+ cout << "Linked list after inserting the node is" << endl;
+ printLinkedList(n0);
+
+ /* ノードを削除 */
+ remove(n0);
+ cout << "Linked list after removing the node is" << endl;
+ printLinkedList(n0);
+
+ /* ノードにアクセス */
+ ListNode *node = access(n0, 3);
+ cout << "The value of the node at index 3 in the linked list = " << node->val << endl;
+
+ /* ノードを検索 */
+ int index = find(n0, 2);
+ cout << "The index of the node with value 2 in the linked list = " << index << endl;
+
+ // メモリを解放
+ freeMemoryLinkedList(n0);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_array_and_linkedlist/list.cpp b/ja/codes/cpp/chapter_array_and_linkedlist/list.cpp
new file mode 100644
index 000000000..62ac38157
--- /dev/null
+++ b/ja/codes/cpp/chapter_array_and_linkedlist/list.cpp
@@ -0,0 +1,72 @@
+/**
+ * File: list.cpp
+ * Created Time: 2022-11-25
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* ドライバーコード */
+int main() {
+ /* リストを初期化 */
+ vector nums = {1, 3, 2, 5, 4};
+ cout << "List nums = ";
+ printVector(nums);
+
+ /* 要素にアクセス */
+ int num = nums[1];
+ cout << "Access the element at index 1, obtained num = " << num << endl;
+
+ /* 要素を更新 */
+ nums[1] = 0;
+ cout << "Update the element at index 1 to 0, resulting in nums = ";
+ printVector(nums);
+
+ /* リストをクリア */
+ nums.clear();
+ cout << "After clearing the list, nums = ";
+ printVector(nums);
+
+ /* 末尾に要素を追加 */
+ nums.push_back(1);
+ nums.push_back(3);
+ nums.push_back(2);
+ nums.push_back(5);
+ nums.push_back(4);
+ cout << "After adding elements, nums = ";
+ printVector(nums);
+
+ /* 中間に要素を挿入 */
+ nums.insert(nums.begin() + 3, 6);
+ cout << "Insert the number 6 at index 3, resulting in nums = ";
+ printVector(nums);
+
+ /* 要素を削除 */
+ nums.erase(nums.begin() + 3);
+ cout << "Remove the element at index 3, resulting in nums = ";
+ printVector(nums);
+
+ /* インデックスによるリストの走査 */
+ int count = 0;
+ for (int i = 0; i < nums.size(); i++) {
+ count += nums[i];
+ }
+ /* リスト要素の走査 */
+ count = 0;
+ for (int x : nums) {
+ count += x;
+ }
+
+ /* 2つのリストを連結 */
+ vector nums1 = {6, 8, 7, 10, 9};
+ nums.insert(nums.end(), nums1.begin(), nums1.end());
+ cout << "Concatenate list nums1 to nums, resulting in nums = ";
+ printVector(nums);
+
+ /* リストをソート */
+ sort(nums.begin(), nums.end());
+ cout << "After sorting the list, nums = ";
+ printVector(nums);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_array_and_linkedlist/my_list.cpp b/ja/codes/cpp/chapter_array_and_linkedlist/my_list.cpp
new file mode 100644
index 000000000..d294f6f63
--- /dev/null
+++ b/ja/codes/cpp/chapter_array_and_linkedlist/my_list.cpp
@@ -0,0 +1,171 @@
+/**
+ * File: my_list.cpp
+ * Created Time: 2022-11-25
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* リストクラス */
+class MyList {
+ private:
+ int *arr; // 配列(リスト要素を格納)
+ int arrCapacity = 10; // リストの容量
+ int arrSize = 0; // リストの長さ(現在の要素数)
+ int extendRatio = 2; // リスト拡張時の倍率
+
+ public:
+ /* コンストラクタ */
+ MyList() {
+ arr = new int[arrCapacity];
+ }
+
+ /* デストラクタ */
+ ~MyList() {
+ delete[] arr;
+ }
+
+ /* リストの長さを取得(現在の要素数)*/
+ int size() {
+ return arrSize;
+ }
+
+ /* リストの容量を取得 */
+ int capacity() {
+ return arrCapacity;
+ }
+
+ /* 要素にアクセス */
+ int get(int index) {
+ // インデックスが範囲外の場合、例外をスロー(以下同様)
+ if (index < 0 || index >= size())
+ throw out_of_range("Index out of bounds");
+ return arr[index];
+ }
+
+ /* 要素を更新 */
+ void set(int index, int num) {
+ if (index < 0 || index >= size())
+ throw out_of_range("Index out of bounds");
+ arr[index] = num;
+ }
+
+ /* 末尾に要素を追加 */
+ void add(int num) {
+ // 要素数が容量を超えた場合、拡張メカニズムをトリガー
+ if (size() == capacity())
+ extendCapacity();
+ arr[size()] = num;
+ // 要素数を更新
+ arrSize++;
+ }
+
+ /* 中間に要素を挿入 */
+ void insert(int index, int num) {
+ if (index < 0 || index >= size())
+ throw out_of_range("Index out of bounds");
+ // 要素数が容量を超えた場合、拡張メカニズムをトリガー
+ if (size() == capacity())
+ extendCapacity();
+ // `index`より後のすべての要素を1つ後ろに移動
+ for (int j = size() - 1; j >= index; j--) {
+ arr[j + 1] = arr[j];
+ }
+ arr[index] = num;
+ // 要素数を更新
+ arrSize++;
+ }
+
+ /* 要素を削除 */
+ int remove(int index) {
+ if (index < 0 || index >= size())
+ throw out_of_range("Index out of bounds");
+ int num = arr[index];
+ // `index`より後のすべての要素を1つ前に移動
+ for (int j = index; j < size() - 1; j++) {
+ arr[j] = arr[j + 1];
+ }
+ // 要素数を更新
+ arrSize--;
+ // 削除された要素を返却
+ return num;
+ }
+
+ /* リストを拡張 */
+ void extendCapacity() {
+ // 元の配列のextendRatio倍の長さで新しい配列を作成
+ int newCapacity = capacity() * extendRatio;
+ int *tmp = arr;
+ arr = new int[newCapacity];
+ // 元の配列のすべての要素を新しい配列にコピー
+ for (int i = 0; i < size(); i++) {
+ arr[i] = tmp[i];
+ }
+ // メモリを解放
+ delete[] tmp;
+ arrCapacity = newCapacity;
+ }
+
+ /* リストをVectorに変換して印刷用に使用 */
+ vector toVector() {
+ // 有効な長さ範囲内の要素のみを変換
+ vector vec(size());
+ for (int i = 0; i < size(); i++) {
+ vec[i] = arr[i];
+ }
+ return vec;
+ }
+};
+
+/* ドライバーコード */
+int main() {
+ /* リストを初期化 */
+ MyList *nums = new MyList();
+ /* 末尾に要素を追加 */
+ nums->add(1);
+ nums->add(3);
+ nums->add(2);
+ nums->add(5);
+ nums->add(4);
+ cout << "List nums = ";
+ vector vec = nums->toVector();
+ printVector(vec);
+ cout << "Capacity = " << nums->capacity() << ", length = " << nums->size() << endl;
+
+ /* 中間に要素を挿入 */
+ nums->insert(3, 6);
+ cout << "Insert the number 6 at index 3, resulting in nums = ";
+ vec = nums->toVector();
+ printVector(vec);
+
+ /* 要素を削除 */
+ nums->remove(3);
+ cout << "Remove the element at index 3, resulting in nums = ";
+ vec = nums->toVector();
+ printVector(vec);
+
+ /* 要素にアクセス */
+ int num = nums->get(1);
+ cout << "Access the element at index 1, obtained num = " << num << endl;
+
+ /* 要素を更新 */
+ nums->set(1, 0);
+ cout << "Update the element at index 1 to 0, resulting in nums = ";
+ vec = nums->toVector();
+ printVector(vec);
+
+ /* 拡張メカニズムをテスト */
+ for (int i = 0; i < 10; i++) {
+ // i = 5の時、リストの長さがリストの容量を超え、この時点で拡張メカニズムがトリガーされる
+ nums->add(i);
+ }
+ cout << "After extending, list nums = ";
+ vec = nums->toVector();
+ printVector(vec);
+ cout << "Capacity = " << nums->capacity() << ", length = " << nums->size() << endl;
+
+ // メモリを解放
+ delete nums;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/n_queens.cpp b/ja/codes/cpp/chapter_backtracking/n_queens.cpp
new file mode 100644
index 000000000..de89dc413
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/n_queens.cpp
@@ -0,0 +1,65 @@
+/**
+ * File: n_queens.cpp
+ * Created Time: 2023-05-04
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* バックトラッキングアルゴリズム:n クイーン */
+void backtrack(int row, int n, vector> &state, vector>> &res, vector &cols,
+ vector &diags1, vector &diags2) {
+ // すべての行が配置されたら、解を記録
+ if (row == n) {
+ res.push_back(state);
+ return;
+ }
+ // すべての列を走査
+ for (int col = 0; col < n; col++) {
+ // セルに対応する主対角線と副対角線を計算
+ int diag1 = row - col + n - 1;
+ int diag2 = row + col;
+ // 剪定:セルの列、主対角線、副対角線にクイーンを配置することを許可しない
+ if (!cols[col] && !diags1[diag1] && !diags2[diag2]) {
+ // 試行:セルにクイーンを配置
+ state[row][col] = "Q";
+ cols[col] = diags1[diag1] = diags2[diag2] = true;
+ // 次の行を配置
+ backtrack(row + 1, n, state, res, cols, diags1, diags2);
+ // 回退:セルを空のスポットに復元
+ state[row][col] = "#";
+ cols[col] = diags1[diag1] = diags2[diag2] = false;
+ }
+ }
+}
+
+/* n クイーンを解く */
+vector>> nQueens(int n) {
+ // n*n サイズのチェスボードを初期化、'Q' はクイーンを表し、'#' は空のスポットを表す
+ vector> state(n, vector(n, "#"));
+ vector cols(n, false); // クイーンのある列を記録
+ vector diags1(2 * n - 1, false); // クイーンのある主対角線を記録
+ vector diags2(2 * n - 1, false); // クイーンのある副対角線を記録
+ vector>> res;
+
+ backtrack(0, n, state, res, cols, diags1, diags2);
+
+ return res;
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 4;
+ vector>> res = nQueens(n);
+
+ cout << "チェスボードの次元を " << n << " として入力" << endl;
+ cout << "クイーン配置解の総数 = " << res.size() << endl;
+ for (const vector> &state : res) {
+ cout << "--------------------" << endl;
+ for (const vector &row : state) {
+ printVector(row);
+ }
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/permutations_i.cpp b/ja/codes/cpp/chapter_backtracking/permutations_i.cpp
new file mode 100644
index 000000000..2d637e71f
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/permutations_i.cpp
@@ -0,0 +1,54 @@
+/**
+ * File: permutations_i.cpp
+ * Created Time: 2023-04-24
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* バックトラッキングアルゴリズム:順列 I */
+void backtrack(vector &state, const vector &choices, vector &selected, vector> &res) {
+ // 状態の長さが要素数と等しくなったら、解を記録
+ if (state.size() == choices.size()) {
+ res.push_back(state);
+ return;
+ }
+ // すべての選択肢を走査
+ for (int i = 0; i < choices.size(); i++) {
+ int choice = choices[i];
+ // 剪定:要素の重複選択を許可しない
+ if (!selected[i]) {
+ // 試行:選択を行い、状態を更新
+ selected[i] = true;
+ state.push_back(choice);
+ // 次のラウンドの選択に進む
+ backtrack(state, choices, selected, res);
+ // 回退:選択を取り消し、前の状態に復元
+ selected[i] = false;
+ state.pop_back();
+ }
+ }
+}
+
+/* 順列 I */
+vector> permutationsI(vector nums) {
+ vector state;
+ vector selected(nums.size(), false);
+ vector> res;
+ backtrack(state, nums, selected, res);
+ return res;
+}
+
+/* ドライバーコード */
+int main() {
+ vector nums = {1, 2, 3};
+
+ vector> res = permutationsI(nums);
+
+ cout << "入力配列 nums = ";
+ printVector(nums);
+ cout << "すべての順列 res = ";
+ printVectorMatrix(res);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/permutations_ii.cpp b/ja/codes/cpp/chapter_backtracking/permutations_ii.cpp
new file mode 100644
index 000000000..0f795da1a
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/permutations_ii.cpp
@@ -0,0 +1,56 @@
+/**
+ * File: permutations_ii.cpp
+ * Created Time: 2023-04-24
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* バックトラッキングアルゴリズム:順列 II */
+void backtrack(vector &state, const vector &choices, vector &selected, vector> &res) {
+ // 状態の長さが要素数と等しくなったら、解を記録
+ if (state.size() == choices.size()) {
+ res.push_back(state);
+ return;
+ }
+ // すべての選択肢を走査
+ unordered_set duplicated;
+ for (int i = 0; i < choices.size(); i++) {
+ int choice = choices[i];
+ // 剪定:要素の重複選択を許可せず、等しい要素の重複選択も許可しない
+ if (!selected[i] && duplicated.find(choice) == duplicated.end()) {
+ // 試行:選択を行い、状態を更新
+ duplicated.emplace(choice); // 選択された要素値を記録
+ selected[i] = true;
+ state.push_back(choice);
+ // 次のラウンドの選択に進む
+ backtrack(state, choices, selected, res);
+ // 回退:選択を取り消し、前の状態に復元
+ selected[i] = false;
+ state.pop_back();
+ }
+ }
+}
+
+/* 順列 II */
+vector> permutationsII(vector nums) {
+ vector state;
+ vector selected(nums.size(), false);
+ vector> res;
+ backtrack(state, nums, selected, res);
+ return res;
+}
+
+/* ドライバーコード */
+int main() {
+ vector nums = {1, 1, 2};
+
+ vector> res = permutationsII(nums);
+
+ cout << "入力配列 nums = ";
+ printVector(nums);
+ cout << "すべての順列 res = ";
+ printVectorMatrix(res);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/preorder_traversal_i_compact.cpp b/ja/codes/cpp/chapter_backtracking/preorder_traversal_i_compact.cpp
new file mode 100644
index 000000000..841d2b7e6
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/preorder_traversal_i_compact.cpp
@@ -0,0 +1,43 @@
+/**
+ * File: preorder_traversal_i_compact.cpp
+ * Created Time: 2023-04-16
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+vector res;
+
+/* 前順走査:例1 */
+void preOrder(TreeNode *root) {
+ if (root == nullptr) {
+ return;
+ }
+ if (root->val == 7) {
+ // 解を記録
+ res.push_back(root);
+ }
+ preOrder(root->left);
+ preOrder(root->right);
+}
+
+/* ドライバーコード */
+int main() {
+ vector arr = {1, 7, 3, 4, 5, 6, 7};
+ TreeNode *root = vecToTree(arr);
+ cout << "\n二分木を初期化" << endl;
+ printTree(root);
+
+ // 前順走査
+ res.clear();
+ preOrder(root);
+
+ cout << "\n値7のノードをすべて出力" << endl;
+ vector vals;
+ for (TreeNode *node : res) {
+ vals.push_back(node->val);
+ }
+ printVector(vals);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/preorder_traversal_ii_compact.cpp b/ja/codes/cpp/chapter_backtracking/preorder_traversal_ii_compact.cpp
new file mode 100644
index 000000000..7a34f6d94
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/preorder_traversal_ii_compact.cpp
@@ -0,0 +1,51 @@
+/**
+ * File: preorder_traversal_ii_compact.cpp
+ * Created Time: 2023-04-16
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+vector path;
+vector> res;
+
+/* 前順走査:例2 */
+void preOrder(TreeNode *root) {
+ if (root == nullptr) {
+ return;
+ }
+ // 試行
+ path.push_back(root);
+ if (root->val == 7) {
+ // 解を記録
+ res.push_back(path);
+ }
+ preOrder(root->left);
+ preOrder(root->right);
+ // 回退
+ path.pop_back();
+}
+
+/* ドライバーコード */
+int main() {
+ vector arr = {1, 7, 3, 4, 5, 6, 7};
+ TreeNode *root = vecToTree(arr);
+ cout << "\n二分木を初期化" << endl;
+ printTree(root);
+
+ // 前順走査
+ path.clear();
+ res.clear();
+ preOrder(root);
+
+ cout << "\nルートからノード7までのすべてのパスを出力" << endl;
+ for (vector &path : res) {
+ vector vals;
+ for (TreeNode *node : path) {
+ vals.push_back(node->val);
+ }
+ printVector(vals);
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/preorder_traversal_iii_compact.cpp b/ja/codes/cpp/chapter_backtracking/preorder_traversal_iii_compact.cpp
new file mode 100644
index 000000000..0de63144b
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/preorder_traversal_iii_compact.cpp
@@ -0,0 +1,52 @@
+/**
+ * File: preorder_traversal_iii_compact.cpp
+ * Created Time: 2023-04-16
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+vector path;
+vector> res;
+
+/* 前順走査:例3 */
+void preOrder(TreeNode *root) {
+ // 剪定
+ if (root == nullptr || root->val == 3) {
+ return;
+ }
+ // 試行
+ path.push_back(root);
+ if (root->val == 7) {
+ // 解を記録
+ res.push_back(path);
+ }
+ preOrder(root->left);
+ preOrder(root->right);
+ // 回退
+ path.pop_back();
+}
+
+/* ドライバーコード */
+int main() {
+ vector arr = {1, 7, 3, 4, 5, 6, 7};
+ TreeNode *root = vecToTree(arr);
+ cout << "\n二分木を初期化" << endl;
+ printTree(root);
+
+ // 前順走査
+ path.clear();
+ res.clear();
+ preOrder(root);
+
+ cout << "\nルートからノード7までのすべてのパスを出力、値3のノードは含まない" << endl;
+ for (vector &path : res) {
+ vector vals;
+ for (TreeNode *node : path) {
+ vals.push_back(node->val);
+ }
+ printVector(vals);
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/preorder_traversal_iii_template.cpp b/ja/codes/cpp/chapter_backtracking/preorder_traversal_iii_template.cpp
new file mode 100644
index 000000000..8c6f976ee
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/preorder_traversal_iii_template.cpp
@@ -0,0 +1,79 @@
+/**
+ * File: preorder_traversal_iii_template.cpp
+ * Created Time: 2023-04-16
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 現在の状態が解かどうかを判定 */
+bool isSolution(vector &state) {
+ return !state.empty() && state.back()->val == 7;
+}
+
+/* 解を記録 */
+void recordSolution(vector &state, vector> &res) {
+ res.push_back(state);
+}
+
+/* 現在の状態下で選択が合法かどうかを判定 */
+bool isValid(vector &state, TreeNode *choice) {
+ return choice != nullptr && choice->val != 3;
+}
+
+/* 状態を更新 */
+void makeChoice(vector &state, TreeNode *choice) {
+ state.push_back(choice);
+}
+
+/* 状態を復元 */
+void undoChoice(vector &state, TreeNode *choice) {
+ state.pop_back();
+}
+
+/* バックトラッキングアルゴリズム:例3 */
+void backtrack(vector &state, vector &choices, vector> &res) {
+ // 解かどうかをチェック
+ if (isSolution(state)) {
+ // 解を記録
+ recordSolution(state, res);
+ }
+ // すべての選択肢を走査
+ for (TreeNode *choice : choices) {
+ // 剪定:選択が合法かどうかをチェック
+ if (isValid(state, choice)) {
+ // 試行:選択を行い、状態を更新
+ makeChoice(state, choice);
+ // 次のラウンドの選択に進む
+ vector nextChoices{choice->left, choice->right};
+ backtrack(state, nextChoices, res);
+ // 回退:選択を取り消し、前の状態に復元
+ undoChoice(state, choice);
+ }
+ }
+}
+
+/* ドライバーコード */
+int main() {
+ vector arr = {1, 7, 3, 4, 5, 6, 7};
+ TreeNode *root = vecToTree(arr);
+ cout << "\n二分木を初期化" << endl;
+ printTree(root);
+
+ // バックトラッキングアルゴリズム
+ vector state;
+ vector choices = {root};
+ vector> res;
+ backtrack(state, choices, res);
+
+ cout << "\nルートからノード7までのすべてのパスを出力、パスには値3のノードを含まないことが要求される" << endl;
+ for (vector &path : res) {
+ vector vals;
+ for (TreeNode *node : path) {
+ vals.push_back(node->val);
+ }
+ printVector(vals);
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/subset_sum_i.cpp b/ja/codes/cpp/chapter_backtracking/subset_sum_i.cpp
new file mode 100644
index 000000000..72c49f4df
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/subset_sum_i.cpp
@@ -0,0 +1,57 @@
+/**
+ * File: subset_sum_i.cpp
+ * Created Time: 2023-06-21
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* バックトラッキングアルゴリズム:部分集合和 I */
+void backtrack(vector &state, int target, vector &choices, int start, vector> &res) {
+ // 部分集合の和がtargetと等しいとき、解を記録
+ if (target == 0) {
+ res.push_back(state);
+ return;
+ }
+ // すべての選択肢を走査
+ // 剪定二:startから走査を開始し、重複する部分集合の生成を回避
+ for (int i = start; i < choices.size(); i++) {
+ // 剪定一:部分集合の和がtargetを超えた場合、即座にループを終了
+ // 配列がソートされているため、後の要素はさらに大きく、部分集合の和は必ずtargetを超える
+ if (target - choices[i] < 0) {
+ break;
+ }
+ // 試行:選択を行い、target、startを更新
+ state.push_back(choices[i]);
+ // 次のラウンドの選択に進む
+ backtrack(state, target - choices[i], choices, i, res);
+ // 回退:選択を取り消し、前の状態に復元
+ state.pop_back();
+ }
+}
+
+/* 部分集合和 I を解く */
+vector> subsetSumI(vector nums, int target) {
+ vector state; // 状態(部分集合)
+ sort(nums.begin(), nums.end()); // nums をソート
+ int start = 0; // 走査の開始点
+ vector> res; // 結果リスト(部分集合リスト)
+ backtrack(state, target, nums, start, res);
+ return res;
+}
+
+/* ドライバーコード */
+int main() {
+ vector nums = {3, 4, 5};
+ int target = 9;
+
+ vector> res = subsetSumI(nums, target);
+
+ cout << "入力配列 nums = ";
+ printVector(nums);
+ cout << "target = " << target << endl;
+ cout << "和が " << target << " のすべての部分集合 res = " << endl;
+ printVectorMatrix(res);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/subset_sum_i_naive.cpp b/ja/codes/cpp/chapter_backtracking/subset_sum_i_naive.cpp
new file mode 100644
index 000000000..8fcf2b7cc
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/subset_sum_i_naive.cpp
@@ -0,0 +1,55 @@
+/**
+ * File: subset_sum_i_naive.cpp
+ * Created Time: 2023-06-21
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* バックトラッキングアルゴリズム:部分集合和 I */
+void backtrack(vector &state, int target, int total, vector &choices, vector> &res) {
+ // 部分集合の和がtargetと等しいとき、解を記録
+ if (total == target) {
+ res.push_back(state);
+ return;
+ }
+ // すべての選択肢を走査
+ for (int i = 0; i < choices.size(); i++) {
+ // 剪定:部分集合の和がtargetを超えた場合、その選択をスキップ
+ if (total + choices[i] > target) {
+ continue;
+ }
+ // 試行:選択を行い、要素とtotalを更新
+ state.push_back(choices[i]);
+ // 次のラウンドの選択に進む
+ backtrack(state, target, total + choices[i], choices, res);
+ // 回退:選択を取り消し、前の状態に復元
+ state.pop_back();
+ }
+}
+
+/* 部分集合和 I を解く(重複する部分集合を含む) */
+vector> subsetSumINaive(vector nums, int target) {
+ vector state; // 状態(部分集合)
+ int total = 0; // 部分集合の和
+ vector> res; // 結果リスト(部分集合リスト)
+ backtrack(state, target, total, nums, res);
+ return res;
+}
+
+/* ドライバーコード */
+int main() {
+ vector nums = {3, 4, 5};
+ int target = 9;
+
+ vector> res = subsetSumINaive(nums, target);
+
+ cout << "入力配列 nums = ";
+ printVector(nums);
+ cout << "target = " << target << endl;
+ cout << "和が " << target << " のすべての部分集合 res = " << endl;
+ printVectorMatrix(res);
+ cout << "この方法の結果には重複する集合が含まれています" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_backtracking/subset_sum_ii.cpp b/ja/codes/cpp/chapter_backtracking/subset_sum_ii.cpp
new file mode 100644
index 000000000..4649d51b2
--- /dev/null
+++ b/ja/codes/cpp/chapter_backtracking/subset_sum_ii.cpp
@@ -0,0 +1,62 @@
+/**
+ * File: subset_sum_ii.cpp
+ * Created Time: 2023-06-21
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* バックトラッキングアルゴリズム:部分集合和 II */
+void backtrack(vector &state, int target, vector &choices, int start, vector> &res) {
+ // 部分集合の和がtargetと等しいとき、解を記録
+ if (target == 0) {
+ res.push_back(state);
+ return;
+ }
+ // すべての選択肢を走査
+ // 剪定二:startから走査を開始し、重複する部分集合の生成を回避
+ // 剪定三:startから走査を開始し、同じ要素の繰り返し選択を回避
+ for (int i = start; i < choices.size(); i++) {
+ // 剪定一:部分集合の和がtargetを超えた場合、即座にループを終了
+ // 配列がソートされているため、後の要素はさらに大きく、部分集合の和は必ずtargetを超える
+ if (target - choices[i] < 0) {
+ break;
+ }
+ // 剪定四:要素が左の要素と等しい場合、検索ブランチの重複を示すのでスキップ
+ if (i > start && choices[i] == choices[i - 1]) {
+ continue;
+ }
+ // 試行:選択を行い、target、startを更新
+ state.push_back(choices[i]);
+ // 次のラウンドの選択に進む
+ backtrack(state, target - choices[i], choices, i + 1, res);
+ // 回退:選択を取り消し、前の状態に復元
+ state.pop_back();
+ }
+}
+
+/* 部分集合和 II を解く */
+vector> subsetSumII(vector nums, int target) {
+ vector state; // 状態(部分集合)
+ sort(nums.begin(), nums.end()); // nums をソート
+ int start = 0; // 走査の開始点
+ vector> res; // 結果リスト(部分集合リスト)
+ backtrack(state, target, nums, start, res);
+ return res;
+}
+
+/* ドライバーコード */
+int main() {
+ vector nums = {4, 4, 5};
+ int target = 9;
+
+ vector> res = subsetSumII(nums, target);
+
+ cout << "入力配列 nums = ";
+ printVector(nums);
+ cout << "target = " << target << endl;
+ cout << "和が " << target << " のすべての部分集合 res = " << endl;
+ printVectorMatrix(res);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_computational_complexity/iteration.cpp b/ja/codes/cpp/chapter_computational_complexity/iteration.cpp
new file mode 100644
index 000000000..4ad0f399b
--- /dev/null
+++ b/ja/codes/cpp/chapter_computational_complexity/iteration.cpp
@@ -0,0 +1,76 @@
+/**
+ * File: iteration.cpp
+ * Created Time: 2023-08-24
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* for ループ */
+int forLoop(int n) {
+ int res = 0;
+ // 1, 2, ..., n-1, n の合計をループ計算
+ for (int i = 1; i <= n; ++i) {
+ res += i;
+ }
+ return res;
+}
+
+/* while ループ */
+int whileLoop(int n) {
+ int res = 0;
+ int i = 1; // 条件変数を初期化
+ // 1, 2, ..., n-1, n の合計をループ計算
+ while (i <= n) {
+ res += i;
+ i++; // 条件変数を更新
+ }
+ return res;
+}
+
+/* while ループ(2つの更新) */
+int whileLoopII(int n) {
+ int res = 0;
+ int i = 1; // 条件変数を初期化
+ // 1, 4, 10, ... の合計をループ計算
+ while (i <= n) {
+ res += i;
+ // 条件変数を更新
+ i++;
+ i *= 2;
+ }
+ return res;
+}
+
+/* 2重 for ループ */
+string nestedForLoop(int n) {
+ ostringstream res;
+ // ループ i = 1, 2, ..., n-1, n
+ for (int i = 1; i <= n; ++i) {
+ // ループ j = 1, 2, ..., n-1, n
+ for (int j = 1; j <= n; ++j) {
+ res << "(" << i << ", " << j << "), ";
+ }
+ }
+ return res.str();
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 5;
+ int res;
+
+ res = forLoop(n);
+ cout << "\nfor ループの合計結果 res = " << res << endl;
+
+ res = whileLoop(n);
+ cout << "\nwhile ループの合計結果 res = " << res << endl;
+
+ res = whileLoopII(n);
+ cout << "\nwhile ループ(2つの更新)の合計結果 res = " << res << endl;
+
+ string resStr = nestedForLoop(n);
+ cout << "\n2重 for ループ走査の結果 = " << resStr << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_computational_complexity/recursion.cpp b/ja/codes/cpp/chapter_computational_complexity/recursion.cpp
new file mode 100644
index 000000000..a481f89e8
--- /dev/null
+++ b/ja/codes/cpp/chapter_computational_complexity/recursion.cpp
@@ -0,0 +1,78 @@
+/**
+ * File: recursion.cpp
+ * Created Time: 2023-08-24
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 再帰 */
+int recur(int n) {
+ // 終了条件
+ if (n == 1)
+ return 1;
+ // 再帰:再帰呼び出し
+ int res = recur(n - 1);
+ // 戻り値:結果を返す
+ return n + res;
+}
+
+/* 反復で再帰をシミュレート */
+int forLoopRecur(int n) {
+ // 明示的なスタックを使用してシステムコールスタックをシミュレート
+ stack stack;
+ int res = 0;
+ // 再帰:再帰呼び出し
+ for (int i = n; i > 0; i--) {
+ // 「スタックへのプッシュ」で「再帰」をシミュレート
+ stack.push(i);
+ }
+ // 戻り値:結果を返す
+ while (!stack.empty()) {
+ // 「スタックからのポップ」で「戻り値」をシミュレート
+ res += stack.top();
+ stack.pop();
+ }
+ // res = 1+2+3+...+n
+ return res;
+}
+
+/* 末尾再帰 */
+int tailRecur(int n, int res) {
+ // 終了条件
+ if (n == 0)
+ return res;
+ // 末尾再帰呼び出し
+ return tailRecur(n - 1, res + n);
+}
+
+/* フィボナッチ数列:再帰 */
+int fib(int n) {
+ // 終了条件 f(1) = 0, f(2) = 1
+ if (n == 1 || n == 2)
+ return n - 1;
+ // 再帰呼び出し f(n) = f(n-1) + f(n-2)
+ int res = fib(n - 1) + fib(n - 2);
+ // 結果 f(n) を返す
+ return res;
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 5;
+ int res;
+
+ res = recur(n);
+ cout << "\n再帰関数の合計結果 res = " << res << endl;
+
+ res = forLoopRecur(n);
+ cout << "\n反復を使用して再帰をシミュレートした合計結果 res = " << res << endl;
+
+ res = tailRecur(n, 0);
+ cout << "\n末尾再帰関数の合計結果 res = " << res << endl;
+
+ res = fib(n);
+ cout << "フィボナッチ数列の第 " << n << " 番目の数は " << res << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_computational_complexity/space_complexity.cpp b/ja/codes/cpp/chapter_computational_complexity/space_complexity.cpp
new file mode 100644
index 000000000..2d61b66c8
--- /dev/null
+++ b/ja/codes/cpp/chapter_computational_complexity/space_complexity.cpp
@@ -0,0 +1,107 @@
+/**
+ * File: space_complexity.cpp
+ * Created Time: 2022-11-25
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 関数 */
+int func() {
+ // 何らかの操作を実行
+ return 0;
+}
+
+/* 定数計算量 */
+void constant(int n) {
+ // 定数、変数、オブジェクトは O(1) 空間を占める
+ const int a = 0;
+ int b = 0;
+ vector nums(10000);
+ ListNode node(0);
+ // ループ内の変数は O(1) 空間を占める
+ for (int i = 0; i < n; i++) {
+ int c = 0;
+ }
+ // ループ内の関数は O(1) 空間を占める
+ for (int i = 0; i < n; i++) {
+ func();
+ }
+}
+
+/* 線形計算量 */
+void linear(int n) {
+ // 長さ n の配列は O(n) 空間を占める
+ vector nums(n);
+ // 長さ n のリストは O(n) 空間を占める
+ vector nodes;
+ for (int i = 0; i < n; i++) {
+ nodes.push_back(ListNode(i));
+ }
+ // 長さ n のハッシュテーブルは O(n) 空間を占める
+ unordered_map map;
+ for (int i = 0; i < n; i++) {
+ map[i] = to_string(i);
+ }
+}
+
+/* 線形計算量(再帰実装) */
+void linearRecur(int n) {
+ cout << "再帰 n = " << n << endl;
+ if (n == 1)
+ return;
+ linearRecur(n - 1);
+}
+
+/* 二次計算量 */
+void quadratic(int n) {
+ // 二次元リストは O(n^2) 空間を占める
+ vector> numMatrix;
+ for (int i = 0; i < n; i++) {
+ vector tmp;
+ for (int j = 0; j < n; j++) {
+ tmp.push_back(0);
+ }
+ numMatrix.push_back(tmp);
+ }
+}
+
+/* 二次計算量(再帰実装) */
+int quadraticRecur(int n) {
+ if (n <= 0)
+ return 0;
+ vector nums(n);
+ cout << "再帰 n = " << n << ", nums の長さ = " << nums.size() << endl;
+ return quadraticRecur(n - 1);
+}
+
+/* 指数計算量(完全二分木の構築) */
+TreeNode *buildTree(int n) {
+ if (n == 0)
+ return nullptr;
+ TreeNode *root = new TreeNode(0);
+ root->left = buildTree(n - 1);
+ root->right = buildTree(n - 1);
+ return root;
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 5;
+ // 定数計算量
+ constant(n);
+ // 線形計算量
+ linear(n);
+ linearRecur(n);
+ // 二次計算量
+ quadratic(n);
+ quadraticRecur(n);
+ // 指数計算量
+ TreeNode *root = buildTree(n);
+ printTree(root);
+
+ // メモリを解放
+ freeMemoryTree(root);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_computational_complexity/time_complexity.cpp b/ja/codes/cpp/chapter_computational_complexity/time_complexity.cpp
new file mode 100644
index 000000000..c20257b8e
--- /dev/null
+++ b/ja/codes/cpp/chapter_computational_complexity/time_complexity.cpp
@@ -0,0 +1,168 @@
+/**
+ * File: time_complexity.cpp
+ * Created Time: 2022-11-25
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 定数計算量 */
+int constant(int n) {
+ int count = 0;
+ int size = 100000;
+ for (int i = 0; i < size; i++)
+ count++;
+ return count;
+}
+
+/* 線形計算量 */
+int linear(int n) {
+ int count = 0;
+ for (int i = 0; i < n; i++)
+ count++;
+ return count;
+}
+
+/* 線形計算量(配列の走査) */
+int arrayTraversal(vector &nums) {
+ int count = 0;
+ // ループ回数は配列の長さに比例
+ for (int num : nums) {
+ count++;
+ }
+ return count;
+}
+
+/* 二次計算量 */
+int quadratic(int n) {
+ int count = 0;
+ // ループ回数はデータサイズ n の二乗に比例
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ count++;
+ }
+ }
+ return count;
+}
+
+/* 二次計算量(バブルソート) */
+int bubbleSort(vector &nums) {
+ int count = 0; // カウンター
+ // 外側ループ:未ソート範囲は [0, i]
+ for (int i = nums.size() - 1; i > 0; i--) {
+ // 内側ループ:未ソート範囲 [0, i] の最大要素を範囲の右端にスワップ
+ for (int j = 0; j < i; j++) {
+ if (nums[j] > nums[j + 1]) {
+ // nums[j] と nums[j + 1] をスワップ
+ int tmp = nums[j];
+ nums[j] = nums[j + 1];
+ nums[j + 1] = tmp;
+ count += 3; // 要素のスワップには3つの個別操作が含まれる
+ }
+ }
+ }
+ return count;
+}
+
+/* 指数計算量(ループ実装) */
+int exponential(int n) {
+ int count = 0, base = 1;
+ // セルは毎ラウンド2つに分裂し、数列 1, 2, 4, 8, ..., 2^(n-1) を形成
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < base; j++) {
+ count++;
+ }
+ base *= 2;
+ }
+ // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
+ return count;
+}
+
+/* 指数計算量(再帰実装) */
+int expRecur(int n) {
+ if (n == 1)
+ return 1;
+ return expRecur(n - 1) + expRecur(n - 1) + 1;
+}
+
+/* 対数計算量(ループ実装) */
+int logarithmic(int n) {
+ int count = 0;
+ while (n > 1) {
+ n = n / 2;
+ count++;
+ }
+ return count;
+}
+
+/* 対数計算量(再帰実装) */
+int logRecur(int n) {
+ if (n <= 1)
+ return 0;
+ return logRecur(n / 2) + 1;
+}
+
+/* 線形対数計算量 */
+int linearLogRecur(int n) {
+ if (n <= 1)
+ return 1;
+ int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);
+ for (int i = 0; i < n; i++) {
+ count++;
+ }
+ return count;
+}
+
+/* 階乗計算量(再帰実装) */
+int factorialRecur(int n) {
+ if (n == 0)
+ return 1;
+ int count = 0;
+ // 1から n に分裂
+ for (int i = 0; i < n; i++) {
+ count += factorialRecur(n - 1);
+ }
+ return count;
+}
+
+/* ドライバーコード */
+int main() {
+ // n を変更して、さまざまな計算量での操作回数の変化傾向を体験可能
+ int n = 8;
+ cout << "入力データサイズ n = " << n << endl;
+
+ int count = constant(n);
+ cout << "定数計算量の操作回数 = " << count << endl;
+
+ count = linear(n);
+ cout << "線形計算量の操作回数 = " << count << endl;
+ vector arr(n);
+ count = arrayTraversal(arr);
+ cout << "線形計算量の操作回数(配列走査) = " << count << endl;
+
+ count = quadratic(n);
+ cout << "二次計算量の操作回数 = " << count << endl;
+ vector nums(n);
+ for (int i = 0; i < n; i++)
+ nums[i] = n - i; // [n,n-1,...,2,1]
+ count = bubbleSort(nums);
+ cout << "二次計算量の操作回数(バブルソート) = " << count << endl;
+
+ count = exponential(n);
+ cout << "指数計算量の操作回数(ループ実装) = " << count << endl;
+ count = expRecur(n);
+ cout << "指数計算量の操作回数(再帰実装) = " << count << endl;
+
+ count = logarithmic(n);
+ cout << "対数計算量の操作回数(ループ実装) = " << count << endl;
+ count = logRecur(n);
+ cout << "対数計算量の操作回数(再帰実装) = " << count << endl;
+
+ count = linearLogRecur(n);
+ cout << "線形対数計算量の操作回数(再帰実装) = " << count << endl;
+
+ count = factorialRecur(n);
+ cout << "階乗計算量の操作回数(再帰実装) = " << count << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_computational_complexity/worst_best_time_complexity.cpp b/ja/codes/cpp/chapter_computational_complexity/worst_best_time_complexity.cpp
new file mode 100644
index 000000000..517a610be
--- /dev/null
+++ b/ja/codes/cpp/chapter_computational_complexity/worst_best_time_complexity.cpp
@@ -0,0 +1,45 @@
+/**
+ * File: worst_best_time_complexity.cpp
+ * Created Time: 2022-11-25
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 要素 {1, 2, ..., n} をランダムにシャッフルした配列を生成 */
+vector randomNumbers(int n) {
+ vector nums(n);
+ // 配列 nums = { 1, 2, 3, ..., n } を生成
+ for (int i = 0; i < n; i++) {
+ nums[i] = i + 1;
+ }
+ // システム時刻を使用してランダムシードを生成
+ unsigned seed = chrono::system_clock::now().time_since_epoch().count();
+ // 配列要素をランダムにシャッフル
+ shuffle(nums.begin(), nums.end(), default_random_engine(seed));
+ return nums;
+}
+
+/* 配列 nums で数値1のインデックスを見つける */
+int findOne(vector &nums) {
+ for (int i = 0; i < nums.size(); i++) {
+ // 要素1が配列の先頭にある場合、最良時間計算量 O(1) を達成
+ // 要素1が配列の末尾にある場合、最悪時間計算量 O(n) を達成
+ if (nums[i] == 1)
+ return i;
+ }
+ return -1;
+}
+
+/* ドライバーコード */
+int main() {
+ for (int i = 0; i < 1000; i++) {
+ int n = 100;
+ vector nums = randomNumbers(n);
+ int index = findOne(nums);
+ cout << "\n配列 [ 1, 2, ..., n ] をシャッフル後 = ";
+ printVector(nums);
+ cout << "数値1のインデックスは " << index << endl;
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_divide_and_conquer/binary_search_recur.cpp b/ja/codes/cpp/chapter_divide_and_conquer/binary_search_recur.cpp
new file mode 100644
index 000000000..ca1c0608c
--- /dev/null
+++ b/ja/codes/cpp/chapter_divide_and_conquer/binary_search_recur.cpp
@@ -0,0 +1,46 @@
+/**
+ * File: binary_search_recur.cpp
+ * Created Time: 2023-07-17
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 二分探索:問題 f(i, j) */
+int dfs(vector &nums, int target, int i, int j) {
+ // 区間が空の場合、対象要素が存在しないことを示すため、-1 を返す
+ if (i > j) {
+ return -1;
+ }
+ // 中点インデックス m を計算
+ int m = i + (j - i) / 2;
+ if (nums[m] < target) {
+ // 再帰的な部分問題 f(m+1, j)
+ return dfs(nums, target, m + 1, j);
+ } else if (nums[m] > target) {
+ // 再帰的な部分問題 f(i, m-1)
+ return dfs(nums, target, i, m - 1);
+ } else {
+ // 対象要素が見つかったため、そのインデックスを返す
+ return m;
+ }
+}
+
+/* 二分探索 */
+int binarySearch(vector &nums, int target) {
+ int n = nums.size();
+ // 問題 f(0, n-1) を解く
+ return dfs(nums, target, 0, n - 1);
+}
+
+/* ドライバーコード */
+int main() {
+ int target = 6;
+ vector nums = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35};
+
+ // 二分探索(両端閉区間)
+ int index = binarySearch(nums, target);
+ cout << "対象要素 6 のインデックス =" << index << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_divide_and_conquer/build_tree.cpp b/ja/codes/cpp/chapter_divide_and_conquer/build_tree.cpp
new file mode 100644
index 000000000..23d3ce215
--- /dev/null
+++ b/ja/codes/cpp/chapter_divide_and_conquer/build_tree.cpp
@@ -0,0 +1,51 @@
+/**
+ * File: build_tree.cpp
+ * Created Time: 2023-07-17
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 二分木の構築:分割統治 */
+TreeNode *dfs(vector &preorder, unordered_map &inorderMap, int i, int l, int r) {
+ // 部分木の区間が空の場合に終了
+ if (r - l < 0)
+ return NULL;
+ // ルートノードを初期化
+ TreeNode *root = new TreeNode(preorder[i]);
+ // m を問い合わせて左右の部分木を分割
+ int m = inorderMap[preorder[i]];
+ // 部分問題:左の部分木を構築
+ root->left = dfs(preorder, inorderMap, i + 1, l, m - 1);
+ // 部分問題:右の部分木を構築
+ root->right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r);
+ // ルートノードを返す
+ return root;
+}
+
+/* 二分木の構築 */
+TreeNode *buildTree(vector &preorder, vector &inorder) {
+ // ハッシュテーブルを初期化し、中間順序の要素からインデックスへのマッピングを格納
+ unordered_map inorderMap;
+ for (int i = 0; i < inorder.size(); i++) {
+ inorderMap[inorder[i]] = i;
+ }
+ TreeNode *root = dfs(preorder, inorderMap, 0, 0, inorder.size() - 1);
+ return root;
+}
+
+/* ドライバーコード */
+int main() {
+ vector preorder = {3, 9, 2, 1, 7};
+ vector inorder = {9, 3, 1, 2, 7};
+ cout << "前順走査 = ";
+ printVector(preorder);
+ cout << "中間順序走査 = ";
+ printVector(inorder);
+
+ TreeNode *root = buildTree(preorder, inorder);
+ cout << "構築された二分木:\n";
+ printTree(root);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_divide_and_conquer/hanota.cpp b/ja/codes/cpp/chapter_divide_and_conquer/hanota.cpp
new file mode 100644
index 000000000..918d7be3c
--- /dev/null
+++ b/ja/codes/cpp/chapter_divide_and_conquer/hanota.cpp
@@ -0,0 +1,66 @@
+/**
+ * File: hanota.cpp
+ * Created Time: 2023-07-17
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 円盤を移動 */
+void move(vector &src, vector &tar) {
+ // src の最上部から円盤を取り出す
+ int pan = src.back();
+ src.pop_back();
+ // 円盤を tar の最上部に配置
+ tar.push_back(pan);
+}
+
+/* ハノイの塔問題 f(i) を解く */
+void dfs(int i, vector &src, vector &buf, vector &tar) {
+ // src に円盤が1つだけ残っている場合、それを tar に移動
+ if (i == 1) {
+ move(src, tar);
+ return;
+ }
+ // 部分問題 f(i-1):tar の助けを借りて、上位 i-1 個の円盤を src から buf に移動
+ dfs(i - 1, src, tar, buf);
+ // 部分問題 f(1):残りの1つの円盤を src から tar に移動
+ move(src, tar);
+ // 部分問題 f(i-1):src の助けを借りて、上位 i-1 個の円盤を buf から tar に移動
+ dfs(i - 1, buf, src, tar);
+}
+
+/* ハノイの塔問題を解く */
+void solveHanota(vector &A, vector &B, vector &C) {
+ int n = A.size();
+ // B の助けを借りて、上位 n 個の円盤を A から C に移動
+ dfs(n, A, B, C);
+}
+
+/* ドライバーコード */
+int main() {
+ // リストの末尾が柱の最上部
+ vector A = {5, 4, 3, 2, 1};
+ vector B = {};
+ vector C = {};
+
+ cout << "初期状態:\n";
+ cout << "A =";
+ printVector(A);
+ cout << "B =";
+ printVector(B);
+ cout << "C =";
+ printVector(C);
+
+ solveHanota(A, B, C);
+
+ cout << "円盤移動後:\n";
+ cout << "A =";
+ printVector(A);
+ cout << "B =";
+ printVector(B);
+ cout << "C =";
+ printVector(C);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_backtrack.cpp b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_backtrack.cpp
new file mode 100644
index 000000000..029aff547
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_backtrack.cpp
@@ -0,0 +1,42 @@
+/**
+ * File: climbing_stairs_backtrack.cpp
+ * Created Time: 2023-06-30
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* バックトラッキング */
+void backtrack(vector &choices, int state, int n, vector &res) {
+ // n段目に到達したとき、解の数に1を加える
+ if (state == n)
+ res[0]++;
+ // すべての選択肢を走査
+ for (auto &choice : choices) {
+ // 剪定:n段を超えて登ることを許可しない
+ if (state + choice > n)
+ continue;
+ // 試行:選択を行い、状態を更新
+ backtrack(choices, state + choice, n, res);
+ // 撤回
+ }
+}
+
+/* 階段登り:バックトラッキング */
+int climbingStairsBacktrack(int n) {
+ vector choices = {1, 2}; // 1段または2段登ることを選択可能
+ int state = 0; // 0段目から登り始める
+ vector res = {0}; // res[0] を使用して解の数を記録
+ backtrack(choices, state, n, res);
+ return res[0];
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 9;
+
+ int res = climbingStairsBacktrack(n);
+ cout << n << "段の階段を登る解は" << res << "通りです" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_constraint_dp.cpp b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_constraint_dp.cpp
new file mode 100644
index 000000000..c8d317aec
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_constraint_dp.cpp
@@ -0,0 +1,37 @@
+/**
+ * File: climbing_stairs_constraint_dp.cpp
+ * Created Time: 2023-07-01
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 制約付き階段登り:動的プログラミング */
+int climbingStairsConstraintDP(int n) {
+ if (n == 1 || n == 2) {
+ return 1;
+ }
+ // DPテーブルを初期化し、部分問題の解を格納するために使用
+ vector> dp(n + 1, vector(3, 0));
+ // 初期状態:最小の部分問題の解を事前設定
+ dp[1][1] = 1;
+ dp[1][2] = 0;
+ dp[2][1] = 0;
+ dp[2][2] = 1;
+ // 状態遷移:小さな問題から大きな部分問題を段階的に解く
+ for (int i = 3; i <= n; i++) {
+ dp[i][1] = dp[i - 1][2];
+ dp[i][2] = dp[i - 2][1] + dp[i - 2][2];
+ }
+ return dp[n][1] + dp[n][2];
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 9;
+
+ int res = climbingStairsConstraintDP(n);
+ cout << n << "段の階段を登る解は" << res << "通りです" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dfs.cpp b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dfs.cpp
new file mode 100644
index 000000000..37cdbbd56
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dfs.cpp
@@ -0,0 +1,32 @@
+/**
+ * File: climbing_stairs_dfs.cpp
+ * Created Time: 2023-06-30
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 探索 */
+int dfs(int i) {
+ // 既知の dp[1] と dp[2] を返す
+ if (i == 1 || i == 2)
+ return i;
+ // dp[i] = dp[i-1] + dp[i-2]
+ int count = dfs(i - 1) + dfs(i - 2);
+ return count;
+}
+
+/* 階段登り:探索 */
+int climbingStairsDFS(int n) {
+ return dfs(n);
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 9;
+
+ int res = climbingStairsDFS(n);
+ cout << n << "段の階段を登る解は" << res << "通りです" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dfs_mem.cpp b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dfs_mem.cpp
new file mode 100644
index 000000000..df8191eac
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dfs_mem.cpp
@@ -0,0 +1,39 @@
+/**
+ * File: climbing_stairs_dfs_mem.cpp
+ * Created Time: 2023-06-30
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* メモ化探索 */
+int dfs(int i, vector &mem) {
+ // 既知の dp[1] と dp[2] を返す
+ if (i == 1 || i == 2)
+ return i;
+ // dp[i] の記録がある場合、それを返す
+ if (mem[i] != -1)
+ return mem[i];
+ // dp[i] = dp[i-1] + dp[i-2]
+ int count = dfs(i - 1, mem) + dfs(i - 2, mem);
+ // dp[i] を記録
+ mem[i] = count;
+ return count;
+}
+
+/* 階段登り:メモ化探索 */
+int climbingStairsDFSMem(int n) {
+ // mem[i] は i 段目に登る総解数を記録、-1 は記録なしを意味する
+ vector mem(n + 1, -1);
+ return dfs(n, mem);
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 9;
+
+ int res = climbingStairsDFSMem(n);
+ cout << n << "段の階段を登る解は" << res << "通りです" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dp.cpp b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dp.cpp
new file mode 100644
index 000000000..5e96f7416
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/climbing_stairs_dp.cpp
@@ -0,0 +1,49 @@
+/**
+ * File: climbing_stairs_dp.cpp
+ * Created Time: 2023-06-30
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 階段登り:動的プログラミング */
+int climbingStairsDP(int n) {
+ if (n == 1 || n == 2)
+ return n;
+ // DPテーブルを初期化し、部分問題の解を格納するために使用
+ vector dp(n + 1);
+ // 初期状態:最小の部分問題の解を事前設定
+ dp[1] = 1;
+ dp[2] = 2;
+ // 状態遷移:小さな問題から大きな部分問題を段階的に解く
+ for (int i = 3; i <= n; i++) {
+ dp[i] = dp[i - 1] + dp[i - 2];
+ }
+ return dp[n];
+}
+
+/* 階段登り:空間最適化動的プログラミング */
+int climbingStairsDPComp(int n) {
+ if (n == 1 || n == 2)
+ return n;
+ int a = 1, b = 2;
+ for (int i = 3; i <= n; i++) {
+ int tmp = b;
+ b = a + b;
+ a = tmp;
+ }
+ return b;
+}
+
+/* ドライバーコード */
+int main() {
+ int n = 9;
+
+ int res = climbingStairsDP(n);
+ cout << n << "段の階段を登る解は" << res << "通りです" << endl;
+
+ res = climbingStairsDPComp(n);
+ cout << n << "段の階段を登る解は" << res << "通りです" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/coin_change.cpp b/ja/codes/cpp/chapter_dynamic_programming/coin_change.cpp
new file mode 100644
index 000000000..e67f9471f
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/coin_change.cpp
@@ -0,0 +1,70 @@
+/**
+ * File: coin_change.cpp
+ * Created Time: 2023-07-11
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 硬貨両替:動的プログラミング */
+int coinChangeDP(vector &coins, int amt) {
+ int n = coins.size();
+ int MAX = amt + 1;
+ // DPテーブルを初期化
+ vector> dp(n + 1, vector(amt + 1, 0));
+ // 状態遷移:最初の行と最初の列
+ for (int a = 1; a <= amt; a++) {
+ dp[0][a] = MAX;
+ }
+ // 状態遷移:残りの行と列
+ for (int i = 1; i <= n; i++) {
+ for (int a = 1; a <= amt; a++) {
+ if (coins[i - 1] > a) {
+ // 目標金額を超える場合、硬貨 i を選択しない
+ dp[i][a] = dp[i - 1][a];
+ } else {
+ // 選択しない場合と硬貨 i を選択する場合のより小さい値
+ dp[i][a] = min(dp[i - 1][a], dp[i][a - coins[i - 1]] + 1);
+ }
+ }
+ }
+ return dp[n][amt] != MAX ? dp[n][amt] : -1;
+}
+
+/* 硬貨両替:空間最適化動的プログラミング */
+int coinChangeDPComp(vector &coins, int amt) {
+ int n = coins.size();
+ int MAX = amt + 1;
+ // DPテーブルを初期化
+ vector dp(amt + 1, MAX);
+ dp[0] = 0;
+ // 状態遷移
+ for (int i = 1; i <= n; i++) {
+ for (int a = 1; a <= amt; a++) {
+ if (coins[i - 1] > a) {
+ // 目標金額を超える場合、硬貨 i を選択しない
+ dp[a] = dp[a];
+ } else {
+ // 選択しない場合と硬貨 i を選択する場合のより小さい値
+ dp[a] = min(dp[a], dp[a - coins[i - 1]] + 1);
+ }
+ }
+ }
+ return dp[amt] != MAX ? dp[amt] : -1;
+}
+
+/* ドライバーコード */
+int main() {
+ vector coins = {1, 2, 5};
+ int amt = 4;
+
+ // 動的プログラミング
+ int res = coinChangeDP(coins, amt);
+ cout << "目標金額を作るのに必要な最小硬貨数は " << res << " です" << endl;
+
+ // 空間最適化動的プログラミング
+ res = coinChangeDPComp(coins, amt);
+ cout << "目標金額を作るのに必要な最小硬貨数は " << res << " です" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/coin_change_ii.cpp b/ja/codes/cpp/chapter_dynamic_programming/coin_change_ii.cpp
new file mode 100644
index 000000000..4b3bb93dc
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/coin_change_ii.cpp
@@ -0,0 +1,68 @@
+/**
+ * File: coin_change_ii.cpp
+ * Created Time: 2023-07-11
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 硬貨両替 II:動的プログラミング */
+int coinChangeIIDP(vector &coins, int amt) {
+ int n = coins.size();
+ // DPテーブルを初期化
+ vector> dp(n + 1, vector(amt + 1, 0));
+ // 最初の列を初期化
+ for (int i = 0; i <= n; i++) {
+ dp[i][0] = 1;
+ }
+ // 状態遷移
+ for (int i = 1; i <= n; i++) {
+ for (int a = 1; a <= amt; a++) {
+ if (coins[i - 1] > a) {
+ // 目標金額を超える場合、硬貨 i を選択しない
+ dp[i][a] = dp[i - 1][a];
+ } else {
+ // 選択しない場合と硬貨 i を選択する場合の2つの選択肢の合計
+ dp[i][a] = dp[i - 1][a] + dp[i][a - coins[i - 1]];
+ }
+ }
+ }
+ return dp[n][amt];
+}
+
+/* 硬貨両替 II:空間最適化動的プログラミング */
+int coinChangeIIDPComp(vector &coins, int amt) {
+ int n = coins.size();
+ // DPテーブルを初期化
+ vector dp(amt + 1, 0);
+ dp[0] = 1;
+ // 状態遷移
+ for (int i = 1; i <= n; i++) {
+ for (int a = 1; a <= amt; a++) {
+ if (coins[i - 1] > a) {
+ // 目標金額を超える場合、硬貨 i を選択しない
+ dp[a] = dp[a];
+ } else {
+ // 選択しない場合と硬貨 i を選択する場合の2つの選択肢の合計
+ dp[a] = dp[a] + dp[a - coins[i - 1]];
+ }
+ }
+ }
+ return dp[amt];
+}
+
+/* ドライバーコード */
+int main() {
+ vector coins = {1, 2, 5};
+ int amt = 5;
+
+ // 動的プログラミング
+ int res = coinChangeIIDP(coins, amt);
+ cout << "目標金額を作る硬貨の組み合わせ数は " << res << " です" << endl;
+
+ // 空間最適化動的プログラミング
+ res = coinChangeIIDPComp(coins, amt);
+ cout << "目標金額を作る硬貨の組み合わせ数は " << res << " です" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/edit_distance.cpp b/ja/codes/cpp/chapter_dynamic_programming/edit_distance.cpp
new file mode 100644
index 000000000..3abce88b2
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/edit_distance.cpp
@@ -0,0 +1,72 @@
+/**
+ * File: edit_distance.cpp
+ * Created Time: 2023-07-13
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 編集距離:ブルートフォース探索 */
+int editDistanceDFS(string s, string t, int i, int j) {
+ // s と t の両方が空の場合、0 を返す
+ if (i == 0 && j == 0)
+ return 0;
+ // s が空の場合、t の長さを返す
+ if (i == 0)
+ return j;
+ // t が空の場合、s の長さを返す
+ if (j == 0)
+ return i;
+ // 2つの文字が等しい場合、これら2つの文字をスキップ
+ if (s[i - 1] == t[j - 1])
+ return editDistanceDFS(s, t, i - 1, j - 1);
+ // 最小編集数 = 3つの操作(挿入、削除、置換)からの最小編集数 + 1
+ int insert = editDistanceDFS(s, t, i, j - 1);
+ int del = editDistanceDFS(s, t, i - 1, j);
+ int replace = editDistanceDFS(s, t, i - 1, j - 1);
+ // 最小編集数を返す
+ return min(min(insert, del), replace) + 1;
+}
+
+/* 編集距離:動的プログラミング */
+int editDistanceDP(string s, string t) {
+ int n = s.length(), m = t.length();
+ vector> dp(n + 1, vector(m + 1, 0));
+ // 状態遷移:最初の行と最初の列
+ for (int i = 1; i <= n; i++) {
+ dp[i][0] = i;
+ }
+ for (int j = 1; j <= m; j++) {
+ dp[0][j] = j;
+ }
+ // 状態遷移:残りの行と列
+ for (int i = 1; i <= n; i++) {
+ for (int j = 1; j <= m; j++) {
+ if (s[i - 1] == t[j - 1]) {
+ // 2つの文字が等しい場合、これら2つの文字をスキップ
+ dp[i][j] = dp[i - 1][j - 1];
+ } else {
+ // 最小編集数 = 3つの操作(挿入、削除、置換)からの最小編集数 + 1
+ dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
+ }
+ }
+ }
+ return dp[n][m];
+}
+
+/* ドライバーコード */
+int main() {
+ string s = "bag";
+ string t = "pack";
+ int n = s.length(), m = t.length();
+
+ // ブルートフォース探索
+ int res = editDistanceDFS(s, t, n, m);
+ cout << s << " を " << t << " に変更するには最低 " << res << " 回の編集が必要です" << endl;
+
+ // 動的プログラミング
+ res = editDistanceDP(s, t);
+ cout << s << " を " << t << " に変更するには最低 " << res << " 回の編集が必要です" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git a/ja/codes/cpp/chapter_dynamic_programming/knapsack.cpp b/ja/codes/cpp/chapter_dynamic_programming/knapsack.cpp
new file mode 100644
index 000000000..a928d55ac
--- /dev/null
+++ b/ja/codes/cpp/chapter_dynamic_programming/knapsack.cpp
@@ -0,0 +1,84 @@
+/**
+ * File: knapsack.cpp
+ * Created Time: 2023-07-10
+ * Author: krahets (krahets@163.com)
+ */
+
+#include "../utils/common.hpp"
+
+/* 0-1 ナップサック:ブルートフォース探索 */
+int knapsackDFS(vector &wgt, vector &val, int i, int c) {
+ // すべてのアイテムが選択されたか、ナップサックに残り容量がない場合、値 0 を返す
+ if (i == 0 || c == 0) {
+ return 0;
+ }
+ // ナップサックの容量を超える場合、ナップサックに入れないことしか選択できない
+ if (wgt[i - 1] > c) {
+ return knapsackDFS(wgt, val, i - 1, c);
+ }
+ // アイテム i を入れない場合と入れる場合の最大値を計算
+ int no = knapsackDFS(wgt, val, i - 1, c);
+ int yes = knapsackDFS(wgt, val, i - 1, c - wgt[i - 1]) + val[i - 1];
+ // 2つの選択肢のより大きい値を返す
+ return max(no, yes);
+}
+
+/* 0-1 ナップサック:動的プログラミング */
+int knapsackDP(vector &wgt, vector &val, int cap) {
+ int n = wgt.size();
+ // DPテーブルを初期化
+ vector> dp(n + 1, vector(cap + 1, 0));
+ // 状態遷移
+ for (int i = 1; i <= n; i++) {
+ for (int c = 1; c <= cap; c++) {
+ if (wgt[i - 1] > c) {
+ // ナップサックの容量を超える場合、アイテム i を選択しない
+ dp[i][c] = dp[i - 1][c];
+ } else {
+ // 選択しない場合とアイテム i を選択する場合のより大きい値
+ dp[i][c] = max(dp[i - 1][c], dp[i - 1][c - wgt[i - 1]] + val[i - 1]);
+ }
+ }
+ }
+ return dp[n][cap];
+}
+
+/* 0-1 ナップサック:空間最適化動的プログラミング */
+int knapsackDPComp(vector &wgt, vector &val, int cap) {
+ int n = wgt.size();
+ // DPテーブルを初期化
+ vector dp(cap + 1, 0);
+ // 状態遷移
+ for (int i = 1; i <= n; i++) {
+ // 逆順で走査
+ for (int c = cap; c >= 1; c--) {
+ if (wgt[i - 1] <= c) {
+ // 選択しない場合とアイテム i を選択する場合のより大きい値
+ dp[c] = max(dp[c], dp[c - wgt[i - 1]] + val[i - 1]);
+ }
+ }
+ }
+ return dp[cap];
+}
+
+/* ドライバーコード */
+int main() {
+ vector