Pythonで配列を右回転して1~nの連続数列(昇順・降順)にできるか判定するプログラム
問題の概要
n 個の要素を含む数値リスト nums が与えられたとします。nums を任意の回数だけ右に回転(シフト)することで、[1, 2, ..., n](昇順)または [n, n-1, ..., 1](降順)という「最初の n 個の自然数」の並びにできるかどうかを判定します。
たとえば、入力が nums = [5, 6, 1, 2, 3, 4] の場合、4 回右に回転すると [1, 2, 3, 4, 5, 6] になるため、答えは True となります。
解法の考え方
鍵となるのは「隣接する要素の差」に注目することです。1 から n までの数字を環状につなげると、隣り合う数字同士の差は 1 になり、環のつなぎ目(1 と n)の差は n-1 になります。したがって、回転によって昇順・降順の数列にできるためには、配列内のすべての隣接要素の差の絶対値が 1 または n-1 でなければなりません。
逆に、この条件がすべて満たされていれば、その並びは「1~n の環状の順序に沿った一筆書きの経路」となり、適切な位置で切る(=回転する)ことで必ず昇順か降順の数列にできます。
アルゴリズムの手順
- n を nums のサイズとします。
- i を 1 から n-1 まで順に調べます。
- |nums[i-1] - nums[i]| が 1 でも n-1 でもない場合は、False を返します。
- すべての隣接ペアが条件を満たしていれば、True を返します。
Pythonでの実装例
def solve(nums):
n = len(nums)
for i in range(1, n):
if abs(nums[i - 1] - nums[i]) != 1 and abs(nums[i - 1] - nums[i]) != n - 1:
return False
return True
nums = [5, 6, 1, 2, 3, 4]
print(solve(nums))入力
[5, 6, 1, 2, 3, 4]
出力
True
補足:より堅牢にするには
このアルゴリズムは、nums が 1 から n までの数字をそれぞれ 1 回ずつ含んでいることを前提としています。重複や範囲外の値が混入する可能性がある場合は、次のようなチェックを最初に追加しておくと安全です。
if set(nums) != set(range(1, n + 1)):
return False計算量
配列を一度走査するだけなので、時間計算量は O(n)、追加のメモリ使用量は O(1) で済みます。大きな配列でも効率的に判定できるのが特徴です。
-
Pythonで最初のn個の自然数の二乗和を求めるプログラム
この記事では、与えられた問題文に対する解法とそのアプローチについて学びます。具体的には、最初のn個の自然数の二乗和(1² + 2² + 3² + … + n²)を求める方法を、2つの異なる手法を使って解説します。 問題文 正の整数Nが入力として与えられます。このとき、12 + 22 + 32 + … + N2 の値を計算してください。 この問題は、主に以下の2つの方法で解くことができます。 繰り返し処理による乗算と加算の計算 数学の公式を利用した直接計算 アプローチ1:繰り返し処理による計算 この方法では、1からnまでループを実行し、各i(1 ≤ i ≤ n)についてiの二乗を求め、変数s
-
【Python】最初のn個の自然数の立方和を求めるプログラム
本記事では、与えられた問題文を解決するための解法とアプローチについて詳しく解説します。 問題文 − 入力として n が与えられたとき、級数 1³ + 2³ + 3³ + 4³ + …… + n³ の第 n 項までの和を出力する必要があります。 ここでは、この問題を解決するための2つのアプローチを紹介します。 ループを使用した総当たり(ブルートフォース)アプローチ n 個の数の和に関する数学的な公式を利用した解法 アプローチ1:数値を反復処理して各項の和を計算する この方法では、1から n までの各数値を順番に取り出し、その立方値を累積していくことで合計を求めます。ロジックがシンプルで直感