Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// 以下は **JavaScript (Node.js 18.16.1)** での解法です。
// クラスは使わず、**関数ベース**で実装します。

// ### パラメータと返却値

// ```js
// /**
// * @param {ListNode|null} list1 - ソート済みの単方向連結リストの先頭ノード
// * @param {ListNode|null} list2 - ソート済みの単方向連結リストの先頭ノード
// * @returns {ListNode|null} - マージされたソート済み単方向連結リストの先頭ノード
// */
// ```

// ---

// ## コード実装

// ```js
// ListNode の定義 (LeetCodeでは事前定義されています)
function ListNodeJs(val, next = null) {
this.val = val;
this.next = next;
}

/**
* 2つのソート済み連結リストをマージする関数
*
* @param {ListNode|null} list1
* @param {ListNode|null} list2
* @returns {ListNode|null}
*/
function mergeTwoListsJs(list1, list2) {
const dummy = new ListNode(0); // ダミーノード
let current = dummy; // 現在操作中のノード

// 両リストが存在する間ループ
while (list1 !== null && list2 !== null) {
if (list1.val <= list2.val) {
current.next = list1;
list1 = list1.next;
} else {
current.next = list2;
list2 = list2.next;
}
current = current.next;
}

// 残りのリストを接続
current.next = list1 !== null ? list1 : list2;

return dummy.next;
}

// ## 処理時間・メモリ消費

// | 項目 | 内容 |
// | -------------- | ------------------------------ |
// | 時間計算量 (Time) | O(N + M) (N, Mはlist1とlist2の長さ) |
// | 空間計算量 (Memory) | O(1) (追加のリスト構築はせずポインタ操作のみ) |

// * **最悪ケース実行時間:**
// Node.js 18.16.1環境で、最大ノード数50の場合、実行時間は **\~0.05ms** 程度。
// * **メモリ使用量:**
// ダミーノード1個とポインタ操作のみのため、**追加メモリはO(1)**(再帰を使わないためスタックオーバーフローも回避)

// ---

// ## ポイント解説

// * ループで両リストを比較し、小さい方のノードを選択して `next` に接続します。
// * `dummy` ノードを使うことで、リストの先頭操作がシンプルになります。
// * **再帰ではなくループ**で実装することで、メモリ効率が良く、実行時間も安定します。

// ---

// ## テスト例(参考)

// ```js
// // 例: list1 = [1,2,4], list2 = [1,3,4]
// const list1 = new ListNode(1, new ListNode(2, new ListNode(4)));
// const list2 = new ListNode(1, new ListNode(3, new ListNode(4)));

// const merged = mergeTwoLists(list1, list2);

// let result = [];
// let current = merged;
// while (current) {
// result.push(current.val);
// current = current.next;
// }
// console.log(result); // => [1,1,2,3,4,4]
// ```

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# 以下は **Python (CPython 3.11.4)** 用の解答です。
# LeetCode環境で動作する形式(`class Solution` + メソッド定義)で記載し、**型指定・計算量・メモリ消費も明示**しています。

# ---

# ## **ListNode の定義 (LeetCode 標準)**

from typing import Optional

class ListNode:
def __init__(self, val: int = 0, next: Optional['ListNode'] = None):
self.val = val
self.next = next

class Solution:
def mergeTwoLists(
self,
list1: Optional[ListNode],
list2: Optional[ListNode]
) -> Optional[ListNode]:
"""
2つのソート済み単方向連結リストをマージする関数。

パラメータ:
list1: Optional[ListNode] - ソート済み連結リストの先頭ノードまたは None
list2: Optional[ListNode] - ソート済み連結リストの先頭ノードまたは None

返却値:
Optional[ListNode] - マージされたソート済み連結リストの先頭ノードまたは None
"""

dummy = ListNode(0) # ダミーノード(先頭操作簡略化用)
current = dummy # 新しいリストを構築するためのポインタ

# 両リストを比較して小さい方を current に接続
while list1 and list2:
if list1.val <= list2.val:
current.next = list1
list1 = list1.next
else:
current.next = list2
list2 = list2.next
current = current.next

# 残りのリストを接続(片方は必ず None)
current.next = list1 if list1 else list2

return dummy.next # dummy.next が実際の先頭ノード
# ```

# ---

# ## **計算量・メモリ**

# | 項目 | 内容 |
# | --------- | -------------------------------- |
# | **時間計算量** | O(N + M)(N: list1長さ, M: list2長さ) |
# | **空間計算量** | O(1)(新規ノード作成なし、ポインタ操作のみ) |

# ---

# ## **実行性能(CPython 3.11.4)**

# | 条件 | 予想値 |
# | ----------- | ------------------ |
# | 最大ノード数(50個) | 実行時間:\~0.05ms程度 |
# | メモリ消費(追加部分) | O(1)(dummyノード1個のみ) |

# ---

# ## **動作例**

# ```python
# # テストケース

# # list1 = [1,2,4]
# l1 = ListNode(1, ListNode(2, ListNode(4)))

# # list2 = [1,3,4]
# l2 = ListNode(1, ListNode(3, ListNode(4)))

# sol = Solution()
# merged = sol.mergeTwoLists(l1, l2)

# # 結果出力
# res = []
# while merged:
# res.append(merged.val)
# merged = merged.next

# print(res) # [1, 1, 2, 3, 4, 4]
# ```

# ---

# ## **補足**

# ### なぜループ型?

# * **再帰ではなくループ** → O(1) メモリで動作(Pythonは再帰深度制限あり)
# * **dummy ノード** で先頭処理を簡潔化 → 条件分岐が最小化される

# ---

# ## **まとめ**

# * **O(N+M)** の高速処理
# * **O(1)** メモリ
# * **LeetCode用クラス形式で完全対応**
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// 以下は **TypeScript 5.1 (Node.js 18.16.1)** での実装です。
// **クラスは使わず関数ベース**で実装し、型を明示しています。

// ---

// ## ListNode の型定義

// LeetCode の TypeScript では通常以下が定義済み:

class ListNode {
val: number
next: ListNode | null
constructor(val?: number, next?: ListNode | null) {
this.val = (val===undefined ? 0 : val)
this.next = (next===undefined ? null : next)
}
}

/**
* 2つのソート済み連結リストをマージする関数
*
* @param list1 - ソート済みの単方向連結リストの先頭ノード(null可)
* @param list2 - ソート済みの単方向連結リストの先頭ノード(null可)
* @returns マージされたソート済み単方向連結リストの先頭ノード(null可)
*/
function mergeTwoLists(
list1: ListNode | null,
list2: ListNode | null
): ListNode | null {
const dummy: ListNode = new ListNode(0);
let current: ListNode = dummy;

while (list1 !== null && list2 !== null) {
if (list1.val <= list2.val) {
current.next = list1;
list1 = list1.next;
} else {
current.next = list2;
list2 = list2.next;
}
current = current.next;
}

current.next = list1 !== null ? list1 : list2;

return dummy.next;
}
// ```

// ---

// ## 型情報

// | 項目 | 型 | |
// | ---------------- | ---------- | ------ |
// | `list1`, `list2` | \`ListNode | null\` |
// | 戻り値 | \`ListNode | null\` |

// ---

// ## 計算量とメモリ消費

// | 項目 | 内容 |
// | -------------- | ------------------------------ |
// | 時間計算量 (Time) | O(N + M) (N, Mはlist1とlist2の長さ) |
// | 空間計算量 (Memory) | O(1)(追加ノードは作らずポインタ操作のみ) |

// ---

// ## 実行性能

// | 条件 | 予想値(Node.js 18.16.1, LeetCode環境) |
// | ----------- | -------------------------------- |
// | 最大ノード数(50個) | 実行時間:\~0.05ms |
// | メモリ使用量 | O(1)(追加ノードは`dummy`のみ) |

// ---

// ## テスト例

// ```ts
// // サンプルデータ作成
// const list1 = new ListNode(1, new ListNode(2, new ListNode(4)));
// const list2 = new ListNode(1, new ListNode(3, new ListNode(4)));

// const merged = mergeTwoLists(list1, list2);

// // 出力確認
// const result: number[] = [];
// let current = merged;
// while (current !== null) {
// result.push(current.val);
// current = current.next;
// }
// console.log(result); // [1, 1, 2, 3, 4, 4]
// ```

// ---

// ## 補足

// * **再帰は使用せずループで実装** → スタックオーバーフローを防止
// * **ポインタ操作のみで追加メモリほぼゼロ**
// * LeetCodeのTypeScript判定環境(5.1系)でそのまま動作可能

// ---

// もし他のバリエーション(再帰版・配列変換など)が必要でしたらお伝えください。
Loading