文字列計算機
Coordinates 2020-4-24
pass-Huawei two side。
インタビュアーはダイナミックな写真を見せて、私に尋ねました:20分で簡単な文字列計算機を書けますか?
少し考えてみてください。大丈夫です。
それでは、混乱の中で、再帰を使用すると同時にスタックも使用したいと思います。最後に、ヌルポインターの異常が無数にある計算機を作成しました。その後、苦痛から学び、今日は文字列計算機の作成方法を説明します。
まず、文字が数字かどうかを判断する関数が必要です。
public static boolean isNum(char x){
return x>=48 && x<=57;
}//利用ascall码判断是否为数字
それで、アルゴリズムのアイデアを設計する2番目のステップに進みます。
文字列計算機の問題解決のアイデアについては、インターネット上で1つしか見られませんでした。これは、ポーランド語のインフィックス式を使用してサフィックスに変換し、1つずつ計算することです。インタビューの過程で、最初の反応は、再帰を使用してすべての括弧を減らし、次に乗算と除算、加算と減算の順に計算することでした。今日は両方のアイデアを改善します。
アイデア1:ポーランド語の式
最初に、次の式2 + 3 *(6-2)を確認します。入力する式であるこの式は、ポーランド語のインフィックス式です。後置式に変換して、 2 3 6 2- * +
どのようなルールを見つけましたか?つまり、演算子を操作の順序で番号の後に配置します。計算するときは、支援するスタックのみが必要であり、結果を順番に計算できます。アップ。
何人かの友人は言った、私はその考えを理解している、それをどのように書くか?ゆっくり話させてください。
最初のステップでは、いくつかの補助ツールが必要
です。1。文字列
StringBuilder stringBuilder = new StringBuilder();
StringBuilderを使用して、変換されたサフィックス式を格納します。
2.スタック
Stack<Character> stack = new Stack<>();
スタックを使用してストレージを支援します。
3.元の表現の文字形式
char x[] = str.toCharArray();
関数に渡された文字列を文字配列に変換するので、isNum関数を使用して判断すると便利です。
これで、関数は次のようになります
public static String inorder (String str){
Stack<Character> stack = new Stack<>();
char x[] = str.toCharArray();
StringBuilder stringBuilder = new StringBuilder();
retrun null;
}
次に、文字配列全体をトラバースします
public static String inorder (String str){
Stack<Character> stack = new Stack<>();
char x[] = str.toCharArray();
StringBuilder stringBuilder = new StringBuilder();
for(int i=0;i<x.length;i++){
}
retrun null;
}
考えてみてください。アレイをトラバースするときに何をすべきでしょうか。
いくつかの状況があります:
1。現在の文字は数字です
2.現在の文字は演算子です
3.現在の文字は括弧です
ケース1の場合、最終的な接尾辞式では番号が元の順序で配置されているため、結果に追加するだけで済みます。
public static String inorder (String str){
Stack<Character> stack = new Stack<>();
char x[] = str.toCharArray();
StringBuilder stringBuilder = new StringBuilder();
for(int i=0;i<x.length;i++){
if (isNum(x[i])) {
//该字符为数字,直接加入结果
stringBuilder.append(x[i]);
continue;
}
}
retrun null;
}
一部の学生は言った:複数の桁がある場合はどうなりますか?いくつかの改善を行います
public static String inorder (String str){
Stack<Character> stack = new Stack<>();
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&&!isNum(x[i+1]))||i==x.length-1)){
stringBuilder.append(" ");
}
continue;
}
}
retrun null;
}
このステップでは、結果に番号を追加して判断します。現在の文字がすでに最後の文字である場合は、その後にスペースを追加するか、現在の文字の次の文字が番号でない場合は、それも追加します。その後にスペースを追加します。
ケース2と3の場合
、操作中は/記号の優先度が±より高いため、最初に/を処理し、* /に遭遇すると、補助スタックに配置します
if (x[i]=='*'||x[i]=='/'){
stack.push(x[i]);
continue;
}
括弧は乗算や除算よりも優先されます。どうすればよいですか?
スタックの特性を考えると、左括弧に出会ったらスタックに入る必要があり、とりあえず次のように掛け算や割り算と同じレベルだと思います。
if (x[i]=='*'||x[i]=='/'||x[i]=='('){
stack.push(x[i]);
continue;
}
左の括弧に遭遇した後も、括弧の一致ルールである右の括弧が見つかるまで元の論理操作を実行します。
この時点で、スタックを操作し、対応する右の括弧が見つかるまでスタックをループアウトする必要があります。括弧を開くと、括弧内の変換が完了しました。
if (x[i]==')'){
while (!stack.isEmpty()){
if (stack.peek()=='('){
stack.pop();
continue;
}
stringBuilder.append(stack.pop());
}
continue;
}
一部の学生は、それがあまり鮮やかだとは思わないかもしれません。
閉じ括弧の前に(3 + 4)スタックの内容をシミュレートしましょう。スタック
の内容は(+
で、文字列の内容は3 4です。
スタックをポップした後、文字列の内容内容は34 +に
なり、スタックの括弧内に演算子はありません。
この時点で、括弧内の接尾辞の変換は完了しています。
現時点では、バーは問題ありません(取り消し線が引かれています)。生徒たちは、加算と減算についてはどうでしょうか。
加算と減算が発生する場合、いくつかの状況を考慮する必要があり
ます。1。現在のスタックが空で、シンボルが直接スタックに配置されます
。2。現在のスタックが空ではなく、スタックの最上位要素が(、±が括弧内の演算子であることを示します。また、直接スタックに
3。現在のスタックは空ではなく、スタックの最上位要素は空ではありません(これは、±が括弧内にある可能性があることを示していますが、現在の操作順序±は、スタックをポップした後、スタックの最上位要素の後ろに配置する必要があります。 ±スタックに入れる
if (x[i]=='+'||x[i]=='-'){
while (!stack.isEmpty()&&stack.peek()!='('){
stringBuilder.append(stack.pop());
}
stack.push(x[i]);
continue;
}
最後に、returnステートメントを追加して後置式を取得します
return stringBuilder.toString();
完全な機能は次のとおりです
public static String inorder (String str){
Stack<Character> stack = new Stack<>();
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&&!isNum(x[i+1]))||i==x.length-1)){
stringBuilder.append(" ");
}
continue;
}
if (x[i]=='*'||x[i]=='('||x[i]=='/'){
stack.push(x[i]);
continue;
}
if (x[i]==')'){
while (!stack.isEmpty()){
if (stack.peek()=='('){
stack.pop();
continue;
}
stringBuilder.append(stack.pop());
}
continue;
}
if (x[i]=='+'||x[i]=='-'){
while (!stack.isEmpty()&&stack.peek()!='('){
stringBuilder.append(stack.pop());
}
stack.push(x[i]);
continue;
}
}
return stringBuilder.toString();
}
次のステップは、接尾辞式の結果を計算することです。このステップは非常に簡単です。説明はしません。番号をスタックにプッシュし、オペレーターに遭遇したときにスタックをポップし、計算結果を取得した後でスタックを再度プッシュするだけです。
注/および-正しい結果を計算するには、スタックからポップされた2つの番号の順序を逆にする必要があります
public static Integer help(String str){
Stack<Integer> num = new Stack<>();
StringBuilder stringBuilder = new StringBuilder();
char x[] = str.toCharArray();
for (int i =0;i<x.length;i++){
if (isNum(x[i])){
stringBuilder.append(x[i]);
if (i+1==x.length){
num.push(Integer.parseInt(stringBuilder.toString()));
}
if (x[i+1]==' '){
num.push(Integer.parseInt(stringBuilder.toString()));
stringBuilder.delete(0,stringBuilder.length());
continue;
}
}
if (x[i]=='+'){
num.push(num.pop()+num.pop());
}
if (x[i]=='-'){
int a = num.pop();
int b = num.pop();
num.push(b-a);
}
if (x[i]=='*'){
num.push(num.pop()*num.pop());
}
if (x[i]=='/'){
int a = num.pop();
int b = num.pop();
num.push(b/a);
}
}
return num.pop();
}
このようにして、main関数で2つの関数を呼び出して、最終的な計算結果を取得します。
再帰については、2番目の記事を参照してください。