-
Notifications
You must be signed in to change notification settings - Fork 0
Add initial implementation of the "Merge Sorted Array" problem in Typ… #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…eScript, including in-place modification of nums1 and a sorting algorithm. Status and time taken comments included for reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あなたの解答を評価させていただきます!
📊 総合評価:4点 / 10点
✅ 良い点(+4点)
-
✓ 正しく動作する(+2点)
- ロジックは正確で、期待通りの結果が得られます
- In-place修正の要件を満たしています
-
✓ コードが読みやすい(+1点)
- 変数名が明確(
preElement,postElement) - 処理の流れが直感的
- 変数名が明確(
-
✓ 基本的なアプローチ(+1点)
- まずマージ、次にソートという考え方は理解しやすい
❌ 改善が必要な点(-6点)
1. 時間計算量が非効率(-3点)
// あなたのコード:O((m+n)²) - バブルソート
for (let i = 0; i < m + n; i++) { // O(m+n)
for (let j = 0; j < m + n; j++) { // O(m+n)
// 交換処理
}
}問題点:
- ネストしたループで O((m+n)²) の時間計算量
- 両配列がすでにソート済みという重要な情報を活用していない
- 大きなデータセットでは非常に遅い
2. バブルソートの実装ミス(-2点)
for (let i = 0; i < m + n; i++) {
for (let j = 0; j < m + n; j++) { // ❌ ここが問題問題点:
- 内側のループが
m + n - 1まで実行すべき j + 1が配列外を参照する可能性がある- たまたま動いているが、バグの原因になりうる
3. 最適解からかけ離れている(-1点)
- この問題は O(m+n) で解ける典型問題
- ソート済み配列の特性を活かすべき
🎯 最適解(2ポインタ手法)
function merge(nums1: number[], m: number, nums2: number[], n: number): void {
// 後ろから埋めていく(上書きを避けるため)
let i = m - 1; // nums1の有効要素の最後尾
let j = n - 1; // nums2の最後尾
let k = m + n - 1; // 結果配列の最後尾
// 両方の配列に要素が残っている間
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) {
nums1[k] = nums1[i];
i--;
} else {
nums1[k] = nums2[j];
j--;
}
k--;
}
// nums2に残りがあれば埋める
while (j >= 0) {
nums1[k] = nums2[j];
j--;
k--;
}
// nums1の残りは既に正しい位置にあるので処理不要
}📈 計算量の比較
| 解法 | 時間計算量 | 空間計算量 | 評価 |
|---|---|---|---|
| あなたの解答 | O((m+n)²) | O(1) | ❌ 非効率 |
| 最適解 | O(m+n) | O(1) | ✅ 最適 |
具体例で比較
m = 100, n = 100 の場合
- あなたの解法:約 40,000回 の比較・交換
- 最適解:約 200回 の比較・代入
→ 200倍の差!
💡 改善アドバイス
1. 問題の制約を見逃さない
"sorted in non-decreasing order"(ソート済み)
この情報が最も重要なヒントです!
2. 後ろから埋める発想
// ❌ 前から埋めると上書きの危険
[1, 2, 3, 0, 0, 0] ← 前から埋めると1,2,3が消える
// ✅ 後ろから埋めると安全
[1, 2, 3, 0, 0, 0] ← 後ろは空いているので安全3. 2ポインタ手法を学ぶ
この問題は2ポインタ手法の典型例です:
- ポインタ1: nums1の末尾
- ポインタ2: nums2の末尾
- ポインタ3: 書き込み位置
🔧 あなたのコードの修正版
もし現在のアプローチを改善するなら:
function merge(nums1: number[], m: number, nums2: number[], n: number): void {
// Step 1: nums2をnums1の後ろにコピー
for (let i = 0; i < n; i++) {
nums1[m + i] = nums2[i];
}
// Step 2: バブルソートを修正
for (let i = 0; i < m + n - 1; i++) { // -1を追加
for (let j = 0; j < m + n - 1 - i; j++) { // 最適化
if (nums1[j] > nums1[j + 1]) {
// 交換(分割代入を使用)
[nums1[j], nums1[j + 1]] = [nums1[j + 1], nums1[j]];
}
}
}
}ただし、これでも O((m+n)²) なので最適解には劣ります。
📚 学習のヒント
- ソート済み配列の問題 → 2ポインタを検討
- In-place操作 → 後ろから処理を検討
- 時間計算量を意識 → ネストループは避ける
頑張ってください!次は最適解に挑戦してみてくださいね! 🚀
| for (let i = 0; i < m + n; i++) { | ||
| for (let j = 0; j < m + n; j++) { | ||
| const preElement = nums1[j]; | ||
| const postElement = nums1[j + 1]; | ||
| if (preElement > postElement) { | ||
| nums1[j] = postElement; | ||
| nums1[j + 1] = preElement; | ||
| } | ||
| } |
Copilot
AI
Oct 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
現在の実装はバブルソートを使用しており、時間計算量がO((m+n)²)となっています。「Merge Sorted Array」問題では、両方の配列が既にソート済みであるという特性を活かすべきです。推奨される解法は、2つのポインタを使って後ろから要素を配置していく方法で、時間計算量O(m+n)、空間計算量O(1)で実現できます。\n\n改善案:\ntypescript\nexport function merge(nums1: number[], m: number, nums2: number[], n: number): void {\n let i = m - 1; // nums1の最後の有効要素\n let j = n - 1; // nums2の最後の要素\n let k = m + n - 1; // nums1の最後の位置\n \n while (j >= 0) {\n if (i >= 0 && nums1[i] > nums2[j]) {\n nums1[k] = nums1[i];\n i--;\n } else {\n nums1[k] = nums2[j];\n j--;\n }\n k--;\n }\n}\n\nこの解法により、既にソート済みという特性を活用して効率的にマージできます。
| } | ||
|
|
||
| for (let i = 0; i < m + n; i++) { | ||
| for (let j = 0; j < m + n; j++) { |
Copilot
AI
Oct 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
配列の境界チェックが不足しています。jがm + n - 1の時にnums1[j + 1]にアクセスすると、配列の範囲外を参照することになります。ループ条件をj < m + n - 1に変更するか、アクセス前に境界チェックを追加する必要があります。\n\n改善案:\ntypescript\nfor (let j = 0; j < m + n - 1; j++) {\n const preElement = nums1[j];\n const postElement = nums1[j + 1];\n if (preElement > postElement) {\n nums1[j] = postElement;\n nums1[j + 1] = preElement;\n }\n}\n
| for (let j = 0; j < m + n; j++) { | |
| for (let j = 0; j < m + n - 1; j++) { |
Status
Accepted
Time Taken
1 h 20 m 22 s