diff --git a/Mathematics/Fundamentals/HackerRank/Claude/Easy/Reverse Game/ReverseGame.html b/Mathematics/Fundamentals/HackerRank/Claude/Easy/Reverse Game/ReverseGame.html new file mode 100644 index 00000000..2ca300c9 --- /dev/null +++ b/Mathematics/Fundamentals/HackerRank/Claude/Easy/Reverse Game/ReverseGame.html @@ -0,0 +1,1311 @@ + + +
+ + ++ ボール逆順ゲーム — パターン導出による + O(1) + 定数時間解法 +
+ +
+ n 個のボール [0, 1, 2, …, n-1] が並んでいる。
+ 以下の操作をステップ i = 0, 1, …, n-1 の順に実施する:
+
+ 配列[i : n] を in-place で逆順にする
+
+
+ 最終的にボール番号 k が何番目のインデックスにあるかを答える。
+ シミュレーションすると最終配列には明確なパターンがあり、閾値
+ τ = ⌊n/2⌋ を使って O(1) で答えられる。
+
+入力: +2 +3 1 ← n=3, k=1 +5 2 ← n=5, k=2 + +出力: +2 +4+
| + インデックス + | ++ 0 + | ++ 1 + | ++ 2 + | ++ 3 + | ++ 4 + | ++ 5 + | +
|---|---|---|---|---|---|---|
| + 値(ボール番号) + | ++ 5 + | ++ 0 + | ++ 4 + | ++ 1 + | ++ 3 + | ++ 2 + | +
| + グループ + | ++ 偶数 + | ++ 奇数 + | ++ 偶数 + | ++ 奇数 + | ++ 偶数 + | ++ 奇数 + | +
+ 偶数インデックスに大きいボール番号、奇数インデックスに小さいボール番号が交互配置される。 +
++ HackerRank 形式・型注釈付き。競技用と業務用の2パターンを掲載。 +
+from __future__ import annotations
+import sys
+from typing import Final
+
+input = sys.stdin.readline
+
+
+def solve_competitive(n: int, k: int) -> int:
+ """
+ 競技プログラミング向け実装(性能最優先)
+
+ 最終配列パターン:
+ 偶数インデックス: n-1, n-2, n-3, ...
+ 奇数インデックス: 0, 1, 2, ...
+
+ 閾値 tau = n // 2 で分岐:
+ k < tau → 奇数位置 → 2*k + 1
+ k >= tau → 偶数位置 → 2*(n-1-k)
+
+ Time : O(1)
+ Space: O(1)
+ """
+ tau: Final[int] = n >> 1 # n // 2(ビットシフト)
+ if k < tau:
+ return (k << 1) | 1 # 2*k + 1
+ return (n - 1 - k) << 1 # 2*(n-1-k)
+
+
+def solve_production(n: int, k: int) -> int:
+ """
+ 業務開発向け実装(型安全・エラーハンドリング重視)
+
+ Args:
+ n: ボールの総数 (n >= 1)
+ k: 検索するボール番号 (0 <= k < n)
+ Returns:
+ ボール k の最終インデックス (0-based)
+ Raises:
+ ValueError: n または k が制約を満たさない場合
+ """
+ if n < 1:
+ raise ValueError(f"n must be >= 1, got {n}")
+ if not (0 <= k < n):
+ raise ValueError(f"k must satisfy 0 <= k < n, got k={k}, n={n}")
+
+ tau: Final[int] = n // 2
+
+ # k < tau → 奇数インデックスに配置 → 2*k + 1
+ if k < tau:
+ return 2 * k + 1
+
+ # k >= tau → 偶数インデックスに配置 → 2*(n-1-k)
+ return 2 * (n - 1 - k)
+
+
+if __name__ == "__main__":
+ t: int = int(input().strip())
+ for _ in range(t):
+ parts = input().rstrip().split()
+ n_val: int = int(parts[0])
+ k_val: int = int(parts[1])
+ print(solve_competitive(n_val, k_val))
+
+
+ フローの説明:
+ 1. n と k を受け取り、閾値
+ τ = ⌊n/2⌋ を計算する。
+ 2.
+ k < τ なら奇数インデックス側 →
+ 2·k + 1
+ を返す。
+ 3. k ≥ τ なら偶数インデックス側 →
+ 2·(n−1−k)
+ を返す。
+ 4. テストケース数 t 回だけループする(紫の破線)。
+
| + アプローチ + | ++ 時間計算量 + | ++ 空間計算量 + | ++ 備考 + | +
|---|---|---|---|
| + ✅ 本手法(数式導出) + | ++ O(1) + | ++ O(1) + | ++ 閾値判定と算術演算のみ。採用。 + | +
| + ナイーブ シミュレーション + | ++ O(n²) + | ++ O(n) + | ++ n 回の逆順各 O(n)。大きい n でTLE。 + | +
| + 部分観察(1ステップ記録) + | ++ O(n) + | ++ O(n) + | ++ シミュレーションを1回に削減可能だが不要。 + | +
n >> 1 … n // 2(ビットシフト)k << 1 … 2 * k(ビットシフト)(k << 1) | 1 … 2*k + 1(ビット演算)sys.stdin.readline … I/O 3倍高速化