2016-12-13 13 views
1

文字列が与えられた場合、文字列中の小文字の「x」文字の数を再帰的に(ループなしで)計算します。Java与えられた文字列のxを再帰的に数える

countX( "xxhixx")→4

countX( "xhixhix")→3

countX( "こんにちは")→0

私の試み:

public int countX(String str) { 
    int sum = 1; 
    if(str.length()-1==0){ 
    return sum; 
    } 
    else{ 
    if(str.charAt(0)=='x'){ 
     return sum+countX(str.substring(1)); 

    } 
    if(str.charAt(0)!='x'){ 
     return countX(str.substring(1)); 
    } 
    } 
} 

次のエラーメッセージが表示されます。This method must return a result of type int. 私のベースケースが正しいかどうかはわかりません。何かヒント?

+2

条件の外での返品はありません。 – KyleKW

+4

*あなたは '=='と '!='は互いに排他的ですが、コンパイラはそれを認識できません。 '!='の代わりに 'else'を使います。 – chrylis

+0

@chrylis:厳密に言えば、ここでの相互排他性は本当に重要ではありません。重要なことは、2つのifがすべての可能性を使い果たしているということです。それらは重なり合う可能性があり、したがって相互に排他的ではありません。逆に、それらは相互に排他的ですが、すべての可能性を網羅していません。 – NPE

答えて

3

それはスルー機能、すべてのコードパスが値を返さなければならないという要件で、コンパイラはあなたに少し過度に知識をひけらかすされている:おそらく

if(str.charAt(0)=='x'){ 
    return sum+countX(str.substring(1)); 
} 
if(str.charAt(0)!='x'){ 
    return countX(str.substring(1)); 
} 
// <--- there's no return value here 

、コンパイラことを把握でき2つのif文はすべての可能性を排除しますが、そうではありません。場合は、他に沿ってコンパイラを支援する

一つの方法は、単一のように2つのIFSを言い換えである:

if(str.charAt(0)=='x') { 
    return sum+countX(str.substring(1)); 
} else { 
    return countX(str.substring(1)); 
} 
+0

この「int sum」を取り除く方法はありますか?コードは、私が入れた文字列にxがある場合にのみ機能します。 – DerDieDasEhochWas

+0

@DerDieDasEhochWas:基本ケースについて注意深く考えてください。あなたの現在のコードはゼロを返すことはできません。また、長さ1の文字列を正しく処理しません。私はこれらのヒントであなたはそれを解決できると思います。 :-) – NPE

+0

私はそれを手に入れました。どうもありがとう。 :) – DerDieDasEhochWas

0

ないすべてのコードパスは、(ビューのダムコンパイラポイントから)戻っていました。 1つで合計を始めるのも間違っているようです。考えてみましょう:

public int countX(String str) { 
    if(str.length()==0){ 
    return 0; 
    } else if(str.charAt(0)=='x'){ 
    return 1 + countX(str.substring(1)); 
    } else { 
    assert str.charAt(0)!='x'; 
    return countX(str.substring(1)); 
    } 
} 

または:魚を揚げるために

public int countX(String str) { 
    if(str.length()==0){ 
    return 0; 
    } 
    if(str.charAt(0)=='x'){ 
    return 1 + countX(str.substring(1)); 
    } 
    assert str.charAt(0)!='x'; 
    return countX(str.substring(1)); 
} 

多くの方法:

public int countX(String str) { 
    return str.isEmpty() ? 0 : (
    (str.charAt(0)=='x' ? 1 : 0) 
    + countX(str.substring(1)) 
); 
} 

を、より簡潔で読みにくくしたいですか?

public int countX(String str) { 
    return str.isEmpty()?0:countX(str.substring(1))+str.charAt(0)=='x'?1:0; 
} 

申し訳ありませんが、私はコードの難読化玩具に向かって楽しい傾向があります。

+0

番号1と2はすべての場合に機能しません。ナンバー3は確かに動作しますが、私はアサートについて聞いたことはありません。ナンバー4は私を怖がらせたので、私はそれを試しませんでした。 – DerDieDasEhochWas

+0

数字1と2が文字列の長さを正しくチェックしていないことを確認しました。私はそれを元のコードから繰り返し取り出し、他のオプションを表示しようとしていました。私が入力した例だけ - 実際にこれらを実行しましたか? –

+0

アサーションについて:プログラマとして、特定の条件が特定の条件下で論理的に真でなければならないことがわかっています。私たちはこの知識をある意味で捕捉し、 'assert'ステートメントを通してデバッグモードでチェックしてもらうことができます。 'assert'の後の式は' true'に評価されなければならず、アサーションが有効なときにのみ実行されます(通常はデバッグ/開発時間ですが、プロダクションではありません)。 –

0

何かこれを行う必要があります。

public int countX(String str) { 
    int sum = 0; 
    if(str.length()-1!=0){ 
    sum = countX(str.substring(1)); 
    if(str.charAt(0)=='x'){ 
     sum += 1; 
    } 
    } 
    return sum; 
} 

あなたの問題は、場合によってはリターンがないことです。これを回避する 1つの方法は、メソッドの最後に、単一のリターン命令を使用しているか、単にこのようなあなたのコードにいくつかの他の例を追加することができます。

[...] 
    else{ 
    if(str.charAt(0)=='x'){ 
     return sum+countX(str.substring(1)); 
    }else{ 
     return countX(str.substring(1)); 
    } 
    } 
    [...] 
1

どのように明示的に代わりの通過秋の使用についてif/elseの場合、コンパイラを混乱させる可能性があります。

public static int countX(final String str) { 
    //base case 
    if(str.length() == 0) { 
     return 0; 
    } 
    else if(str.length() == 1) { 
     return str.charAt(0) == 'x' ? 1 : 0; 
    } 
    //recursive step 
    return str.charAt(0) == 'x' ? 1 + countX(str.substring(1)) : countX(str.substring(1)); 
} 
+0

空文字列をこのバージョンに渡すと、基底の大文字が少なくとも1つの文字を前提としているため、悪いことが起こります。 –

+0

ありがとうございます。非常に素晴らしい。しかし、もし私が空の文字列を入れたら?私がしている場合、私は範囲外の例外のインデックスを取得します。 – DerDieDasEhochWas

+0

Ok - 回答を更新しました。 –

関連する問題