2017-02-16 6 views
2

私は学生ですが、substringメソッドを使用せずに大きな文字列(干し草)の部分文字列(針)を見つけ、再帰を使用します。再帰は私の強いスーツではありませんが、私は次のように出てきました:予期せぬ方法でJavaで動作する再帰

public class Contains 
{ 
    public static void main(String[] args) 
    { 
     System.out.println(contains("Java programming", "ogr", false)); 
    } 

    public static boolean contains(String haystack, String needle, boolean doesContain) 
    { 
     if(haystack.length() < needle.length()) 
     { 
      return false; 
     } 
     else 
     { 
      for(int i = 0; i < needle.length(); i++) 
      { 
       if(haystack.charAt(i) != needle.charAt(i)) 
        if((i + 1) == needle.length()) 
         { 
          doesContain = false; 
          break; 
         } 
        else 
         break; 
       else 
        if((i + 1) == needle.length()) 
        { 
         doesContain = true; 
         break; 
        } 
        else 
         continue; 
      } 
      char[] haystackChar = haystack.toCharArray(); 
      char[] newCharArray = new char[(haystackChar.length - 1)]; 

      for(int j = 1; j < haystackChar.length; j++) 
      { 
       newCharArray[j - 1] = haystackChar[j]; 
      } 

      String newStr = new String(newCharArray); 

      if(doesContain == false) 
       contains(newStr, needle, doesContain); 
     } 
     return doesContain; 
    } 
} 

私はこれが最善か、最もエレガントな解決策ではないかもしれません実現が、私はほとんどちょうどそれが動作するように取得しようとしています。私はEclipseデバッガでそれを実行していましたが、containへのメソッド呼び出し中にを呼び出すまではすべて期待通りに機能していましたが、forループの繰り返し中にdoesContainがtrueに設定されています。デバッガはdoesContainの値が(正しく)真であることを示しており、if文をスキップしてelseブロックを終了することを示しています。しかし、その直後に、それはelseブロックにジャンプし、doesContainの代わりにcontainへの再帰呼び出しを呼び出します。次に、 "針"が配置されていない文字列の残りの部分を検索しているため、再帰的に動作し続け、失敗してfalseを返します。

私はStackOverflow自体が「宿題の手助け」の場所ではないことを知っていますが、私は学校以外の目的でプログラムしています。なぜこのように振舞っているのか非常に困惑しています。誰がなぜこれをやっているのか知っていますか?私はここに何かを逃していますか

+1

オハイオ州の男、私は答えでスパムになる女の子だったらいいのに!とにかくあなたの(間違いなく形式が不適切な)コードは正常に動作しています。問題は、あなたが再帰呼び出しの結果を破棄していることです。 'newStr、needle、doesContain);'を( 'newStr、needle、doesContain);'と 'vòila! –

答えて

1

私はあなたのコードを見て、自分自身をeclipseで走らせました。調べてみたい理論は、スタッキングがどのように再帰で動作するかです。あなたのプログラムは真実を発見してからスタックを離れるが、その時点までに何度か再発した。それは真実を返しましたが、それ以前に格納されていたすべての偽変数も返すようになりました。

さらにご質問がありましたら、お知らせください。

EDIT あなたが進んで再帰に入る本当に興味があるなら、私は非常にこのビデオをお勧めします:Java Recursion

ねえ、私はそれを動作させるためにそこまでする必要はありませんでした。 doContainをパラメータとして削除し、それを静的インスタンス変数として設定すると、私のために働くことができます。

public class Contains 
{ 

    private static boolean doesContain = false; 

    public static void main(String[] args) 
    { 
     System.out.println(contains("Java programming", "ogr")); 
    } 

    public static boolean contains(String haystack, String needle) 
    { 
     if(haystack.length() < needle.length()) 
     { 
      return false; 
     } 
     else 
     { 
      for(int i = 0; i < needle.length(); i++) 
      { 
       if(haystack.charAt(i) != needle.charAt(i)) 
        if((i + 1) == needle.length()) 
         { 
          doesContain = false; 
          break; 
         } 
        else 
         break; 
       else 
        if((i + 1) == needle.length()) 
        { 
         doesContain = true; 
         break; 
        } 
        else 
         continue; 
      } 
      char[] haystackChar = haystack.toCharArray(); 
      char[] newCharArray = new char[(haystackChar.length - 1)]; 

      for(int j = 1; j < haystackChar.length; j++) 
      { 
       newCharArray[j - 1] = haystackChar[j]; 
      } 

      String newStr = new String(newCharArray); 

      if(doesContain == false) 
       contains(newStr, needle); 
     } 
     return doesContain; 
    } 
} 

あなたが持っていたものは非常に近いものでしたが、別の再帰を経るたびにパラメータとして渡していました。あなたは最終的な価値を返すだけです。

+0

変数をnullに設定すると、どの変数を意味していますか?現在のコードに既に存在するもの、またはこれを評価する目的で新しい変数を追加しますか?あなたがスタックについて何を言っているのか、私は幾分理解しています。 –

+0

ちょっと@AbigailFox、混乱のために申し訳ありません。私が話していたことは、あなたが行く必要があるより少し進んだ。インスタンス変数を設定することによって、1回の複製を保持し、再帰の各ステップごとに1つを保存することはできません。あなたは最終的な価値を返すだけです。 –

+0

ありがとう!できます!あなたの説明のためにもありがとう、再帰的思考はおそらく私が最悪ですプログラミングのスキルです。私は、メソッドがスタックとどのようにやりとりしていたか、繰り返しメソッド呼び出しでブール値がどのように処理されていたかについて実際には考えていませんでした。 –

0

haystackneedleを探したい場合は、再帰を使用する必要はありません。

ちょうどあなたの関数から次のコード行を削除し、それだけで正常に動作します:

 char[] haystackChar = haystack.toCharArray(); 
     char[] newCharArray = new char[(haystackChar.length - 1)]; 

     for(int j = 1; j < haystackChar.length; j++) 
     { 
      newCharArray[j - 1] = haystackChar[j]; 
     } 

     String newStr = new String(newCharArray); 

     if(doesContain == false) 
      contains(newStr, needle, doesContain); 
+0

はい、残念ながら、再帰を使用することは割り当ての要件です。個人的には、再帰を理解するのがはるかに難しいと思っていますが、私はそれをよりうまく使うためには練習をしなければならないことも認識しています。しかし、助けてくれてありがとう! –

0

私はあなたがソートの再帰関数を自分で混乱していると思います。再帰関数に渡される変数の1つはdoesContainですが、関数にはが返されます。戻り値はです。行内

 if(doesContain == false) 
      contains(newStr, needle, doesContain); 

部分文字列に針が含まれている場合は、を呼び出すと戻ります。その値を取って、コールスタックに戻す必要があります。

うまくいけばそれは意味をなさないでしょう。そうでなければ、私はあなた自身でそれを理解することができるようにコードを与えます:

public static boolean contains(String haystack, String needle) 
{ 
    if(haystack.length() < needle.length()) 
    { 
     return false; 
    } 
    else 
    { 
     boolean doesContain=false; 
     for(int i = 0; i < needle.length(); i++) 
     { 
      if(haystack.charAt(i) != needle.charAt(i)) 
       if((i + 1) == needle.length()) 
        { 
         doesContain = false; 
         break; 
        } 
       else 
        break; 
      else 
       if((i + 1) == needle.length()) 
       { 
        doesContain = true; 
        break; 
       } 
       else 
        continue; 
     } 
     char[] haystackChar = haystack.toCharArray(); 
     char[] newCharArray = new char[(haystackChar.length - 1)]; 

     for(int j = 1; j < haystackChar.length; j++) 
     { 
      newCharArray[j - 1] = haystackChar[j]; 
     } 

     String newStr = new String(newCharArray); 

     if(doesContain == false) 
      return contains(newStr, needle); 
     else 
      return true; 
    } 
} 
+0

私は実際にそれを以前と同じようにしました。ブール値をメソッド呼び出しに追加することは、私の問題を解決しようとした修正の1つでした。問題の原因は、メソッドの開始時に 'doesContain'をfalseに設定していたということでした。なぜそれが後ろに飛び跳ねているのか、それを修正しなかったのかを実際には説明していませんでしたが、それがなくても正しい値を返さないのです。 –

+0

@AbigailFox待って、私はそれをテストし、それが動作します。関数から飛び出して、それを呼び出す関数に戻ります。 – AJC

+0

それはどういう意味ですか?それはどうしていますか? –

関連する問題