@MStodd に同意します。再帰は Python でこの問題を解決する方法ではありません。非常に長いリストの場合、Python はそのスタックをオーバーフローする可能性があります! しかし、短いリストの場合は問題ありません。教師がこの問題を出したら、このようにする必要があります。
ここでは、この問題についてどのように考える必要があります。再帰呼び出しごとに、次の 3 つのいずれかを実行する必要があります。0)False
リストがソートされていないことが判明したため、戻ります。1)True
基本ケースに達したため、戻ります。2) 基本ケースに到達するまで、作業を分解し、残りの問題を何とか小さくします。基本ケースは、作業をこれ以上分解できないケースです。
大まかな概要は次のとおりです。
def recursive_check(lst, i):
# check at the current position "i" in list
# if check at current position fails, return False
# update current position i
# if i is at the end of the string, and we cannot move it any more, we are done checking; return true
# else, if i is not at the end of the string yet, return the value returned by a recursive call to this function
たとえば'@'
、文字列に文字があるかどうかを確認する関数を次に示します。文字列のどこにもTrue
ない場合は返されます。@
def at_check(s, i):
if s[i] == '@':
return False
i += 1
if i >= len(s):
return True
else:
return at_check(s, i)
上記のアウトラインとまったく同じように上記を書きました。これは、同じことを行うわずかに短いバージョンですが、まったく同じ順序ではありません。
def at_check(s, i=0):
if i >= len(s):
return True
if s[i] == '@':
return False
return at_check(s, i+1)
i=0
編集:に引数を入れたことに注意してくださいat_check()
。これは、 の「デフォルト」値i
が 0 になることを意味します。この関数を呼び出す人at_check(some_string)
は、最初の呼び出しで明示的に 0 を渡さなくても呼び出すことができます。デフォルトの引数は、最初の 0 引数を提供します。
本当に追加する必要があるi
のは、関数を再帰的に呼び出すときだけです。1を足す部分が重要な「仕事を分解する」部分です。まだチェックしていない文字列の部分は の後の部分でi
、その部分は呼び出すたびに小さくなります。「スライス」についてまだ学んでいるかどうかはわかりませんが、「スライス」を使用して、呼び出しごとに文字列を実際に小さくすることができます。そのように動作するバージョンを次に示します。スライスについてまだ知らない場合は無視してください。
def at_check(s):
if s == '': # empty string
return True
if s[-1] == '@': # is last character '@'?
return False
return at_check(s[:-1]) # recursive call with string shortened by 1
このバージョンでは、空の文字列が基本ケースです。空の文字列には が含まれない@
ため、 を返しTrue
ます。次に、最後の文字が; の場合は;@
を返すことができます。False
それ以外の場合は、最後の文字を切り捨てて、関数を再帰的に呼び出します。ここでは、完了するまで文字列を文字通り短くすることで、作業を分解します。しかし、インデックス変数に 1 を追加することと、文字列内でインデックスを移動することは同じことです。
再帰を使用して作業を分解し、各再帰呼び出しである程度の進歩を遂げるというアイデアが得られるまで、これらの例を調べてください。次に、リストがソートされているかどうかを調べる問題にこのアイデアを適用する方法を理解できるかどうかを確認してください。
幸運を!