文字列計算機をエレガントに書く方法(java再帰)(コードは直接使用できます)

上記のように、前回の記事では、文字列計算機の機能を完成させるために、接尾辞の形式を使用しました。その後、一部の生徒は、接尾辞の接尾辞がわからないと言ったので、直接計算したいのですが。OK、以下をご覧ください。

今回使ったアイデアは、インタビューの過程で最初に思いついた再帰でしたが、インタビュー中に慌てて、20分で整理できませんでした。

今回は、最初に全体的な考え方について説明します。
最初のステップ:文字列全体を数字と記号に分割してリストに保存します
。2番目のステップ:INT型を返す関数を設計し、関数内に2つの関数を実装します。括弧を削除し、加算、減算、乗算、および除算を計算して、関数が複数の括弧を使用して加算、減算、乗算、および除算の操作を再帰的に実行できるようにします。

まず、文字が数字かどうかを判断する関数が必要です

 public static boolean isNum(char c){
    
    
        return c>=48 && c<=57;
    }

次に、各数値と演算子をオブジェクトの文字列に変換し、リストに格納します。

public static List<String> inorder (String str) {
    
    
        ArrayList<String> list = new ArrayList<>();
        char []x = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i=0;i<x.length;i++){
    
    
            if (isNum(x[i])){
    
    
                stringBuilder.append(x[i]);
                if (i==x.length-1||(i<x.length-1&&!isNum(x[i+1]))){
    
    
                    list.add(stringBuilder.toString());
                    stringBuilder.delete(0,stringBuilder.length());
                }
            }else {
    
    
                list.add(String.valueOf(x[i]));
            }
        }
        return list;
    }

数字ごとに、後ろがシンボルか最後の桁かを判断します。この2つの場合は、文字列をリストに保存し、StringBuilderをクリアします。
したがって、例12 + 2 *(4-3)の場合、取得するリストは次のようになります
[12、+、2、*、(、4、-、3、)]

上記では、文字列全体を数字と記号のコレクションに分割し終えました。2番目のステップでは、計算を実行します。(ここでは再帰的思考が使用されます)

Stack<String> stack = new Stack<>();
        int len = list.size();
        for (int i=0;i<len;i++){
    
    
            String x = list.get(i);
            if (x.equals(")"))
            {
    
    
                List<String> lis = new ArrayList<>();
                while (!stack.isEmpty()&&!stack.peek().equals("(")){
    
    
                    lis.add(0,stack.pop());
                }
                stack.pop();
                String m = String.valueOf(help(lis));
                stack.push(m);
                continue;
            }
            stack.push(list.get(i));
        }

これは、括弧を削除する計算関数の最初の部分です。具体的なアイデアは次のとおりです。リストをトラバースして、現在のオブジェクトが「)」の場合、一致させ、新しいリストを作成し、補助スタックからポップする必要があります。 (に遭遇するまで、ブラケットのマッチングが完了するまで、lisに格納されているコンテンツはブラケット内のすべてのコンテンツである必要があります。
再帰-現在の関数は計算結果を返す必要があり、入力値はリストタイプであるため、lisを実行します。 、括弧内のシーケンスである、それ自体を呼び出すと、括弧内の計算結果を取得して補助スタックに追加する必要があります。これで括弧の削除が完了します。
次に、現在のオブジェクトがそうでない場合)、スタックに。

次は計算部分です

 Stack<String> res = new Stack<>();
        while (!stack.isEmpty()){
    
    
            String x = stack.pop();
            if (x.equals("*")){
    
    
                Integer num1 = Integer.valueOf(stack.pop());
                Integer num2 = Integer.valueOf(res.pop());
                res.push(String.valueOf(num1*num2));
                continue;
            }else if (x.equals("/")){
    
    
                Integer num1 = Integer.valueOf(stack.pop());
                Integer num2 = Integer.valueOf(res.pop());
                res.push(String.valueOf(num1/num2));
                continue;
            }
            res.push(x);
        }

乗算と除算に一致する新しい補助スタックresを作成します。乗算と除算のシンボルが見つかった場合は、それぞれスタックとresからオブジェクトをポーリングし、/ *を使用して結果を計算してresに追加する必要があります。
現在のオブジェクトが乗算と除算のシンボルでない場合は、直接resに追加します。

最後のステップは、加算と減算を計算することです

 while (!res.isEmpty()){
    
    
            String x = res.pop();
            if (x.equals("+")){
    
    
                Integer num1 = Integer.valueOf(res.pop());
                Integer num2 = Integer.valueOf(stack.pop());
                stack.push(String.valueOf(num1+num2));
                continue;
            }else if (x.equals("-")){
    
    
                Integer num1 = Integer.valueOf(res.pop());
                Integer num2 = Integer.valueOf(stack.pop());
                stack.push(String.valueOf(num2-num1));
                continue;
            }
            stack.push(x);
        }

考え方は前のステップでの乗算と除算の計算と同じです。除算を計算するとき、スタックから取り出すオブジェクトは配当であり、結果がすべてresに転送されると、シーケンスが逆になり、減算を計算するときに注意する必要があります。 、res内のオブジェクトを減算するには、スタック内のオブジェクトを使用する必要があります。

完全なコード

import java.util.*;
public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner input = new Scanner(System.in);
        String str= input.next();
        List<String> list = inorder(str);
        System.out.println(help(list));


    }
    public static Integer help(List<String> list){
    
    
        Stack<String> stack = new Stack<>();
        int len = list.size();
        for (int i=0;i<len;i++){
    
    
            String x = list.get(i);
            if (x.equals(")"))
            {
    
    
                List<String> lis = new ArrayList<>();
                while (!stack.isEmpty()&&!stack.peek().equals("(")){
    
    
                    lis.add(0,stack.pop());
                }
                stack.pop();
                String m = String.valueOf(help(lis));
                stack.push(m);
                continue;
            }
            stack.push(list.get(i));
        }

        Stack<String> res = new Stack<>();
        while (!stack.isEmpty()){
    
    
            String x = stack.pop();
            if (x.equals("*")){
    
    
                Integer num1 = Integer.valueOf(stack.pop());
                Integer num2 = Integer.valueOf(res.pop());
                res.push(String.valueOf(num1*num2));
                continue;
            }else if (x.equals("/")){
    
    
                Integer num1 = Integer.valueOf(stack.pop());
                Integer num2 = Integer.valueOf(res.pop());
                res.push(String.valueOf(num1/num2));
                continue;
            }
            res.push(x);
        }
        while (!res.isEmpty()){
    
    
            String x = res.pop();
            if (x.equals("+")){
    
    
                Integer num1 = Integer.valueOf(res.pop());
                Integer num2 = Integer.valueOf(stack.pop());
                stack.push(String.valueOf(num1+num2));
                continue;
            }else if (x.equals("-")){
    
    
                Integer num1 = Integer.valueOf(res.pop());
                Integer num2 = Integer.valueOf(stack.pop());
                stack.push(String.valueOf(num2-num1));
                continue;
            }
            stack.push(x);
        }
        return Integer.valueOf(stack.pop());

    }

    public static boolean isNum(char c){
    
    
        return c>=48 && c<=57;
    }
    public static List<String> inorder (String str) {
    
    
        ArrayList<String> list = new ArrayList<>();
        char []x = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i=0;i<x.length;i++){
    
    
            if (isNum(x[i])){
    
    
                stringBuilder.append(x[i]);
                if (i==x.length-1||(i<x.length-1&&!isNum(x[i+1]))){
    
    
                    list.add(stringBuilder.toString());
                    stringBuilder.delete(0,stringBuilder.length());
                }
            }else {
    
    
                list.add(String.valueOf(x[i]));
            }
        }
        return list;
    }
}

以上のように、再帰的思考で書かれたジャバ計算機が完成しました。生徒たちに何かを学んでもらいたいです。PS:同じコードはLeetCodeで機能せず、3/2のユースケースでエラーが報告されましたが、ローカルで実行するのは正しかったです。奇妙な
PS2:リートコードの計算機に括弧がないことがわかりました。(lll¬ω¬)
PS3:3年生のJAVAクラスのプログラミング割り当てが計算機を書くことだったことを突然思い出しましたが、コードはインターネットで見つかりました。それを後悔。
PS4:もう一度少し問題がありましたが、修正は生徒に任せています。乗算と除算を初めて一致させるときは、順番に計算する必要があります。プログラムは逆方向に計算されるため、乗算と除算が順番に発生すると結果にエラーが発生します。 。

おすすめ

転載: blog.csdn.net/qq_45789385/article/details/105755432