算法趣题-----数列的四则运算(Java)

在这里插入图片描述

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class 数列的四则运算 {
    public static void main(String[] args) throws Exception {
        // 运算符号,最后一个为空代表没有运算符
        String[] ops = new String[]{"+","-","*","/",""};
//        String[] ops = new String[]{"*",""};
        for(int i = 1000; i <= 9999; i++) {
            String num = i + "";
            for (String value : ops) {
                for (String s : ops) {
                    for (String op : ops) {
                        String operation = num.charAt(0) + value + num.charAt(1) + s + num.charAt(2) + op + num.charAt(3);
                        if (operation.length() > 4) {
                            List<String> list = toList(operation);
                            List<String> suffix = centerToAfter(list);
                            StringBuilder result = new StringBuilder(Calculate(suffix)).reverse();
                            if (result.toString().equals(num)) {
                                System.out.println("num = " + num);
                                System.out.println("operation = " + operation);
                                System.out.println("list = " + list);
                                System.out.println("suffix = " + suffix);
                                System.out.println("result = " + result);
                                System.out.println("-------------------------------");
                            }
                        }
                    }
                }
            }
        }
    }

    // 将字符串用list装起来
    public static List<String> toList(String operation) {
        List<String> list = new ArrayList<>();
        char c;
        String keepNum;
        for(int i = 0; i < operation.length(); i++) {
            if(!Character.isDigit(c = operation.charAt(i))) {
                list.add(Character.toString(c));
            }else {
                keepNum = "";
                while (i < operation.length() && Character.isDigit(c = operation.charAt(i))) {
                    keepNum += c;
                    i++;
                }
                i--;
                list.add(keepNum);
            }
        }
        return list;
    }

    // 将中缀表达式变为后缀表达式
    public static List<String> centerToAfter(List<String> list) throws Exception {
        Stack<String> stringStack = new Stack<>();
        // 用list就已经相当与栈的逆序了
        List<String> stringList = new ArrayList<>();
        for(String item : list) {
            if(item.matches("\\d+")) {
                stringList.add(item);
            }else {
                if(stringStack.isEmpty()) {
                    stringStack.push(item);
                }else {
                    while (!stringStack.isEmpty() && priority(stringStack.peek()) >= priority(item)) {
                        stringList.add(stringStack.pop());
                    }
                    stringStack.push(item);
                }
            }
        }
        while (!stringStack.isEmpty()) {
            stringList.add(stringStack.pop());
        }
        return stringList;
    }

    // 通过后缀表达式进行计算值
    public static String Calculate(List<String> list) {
        Stack<String> stack = new Stack<>();
        for(String item : list) {
            if(item.matches("\\d+")) {
                stack.push(item);
            }else {
                double num1 = Double.parseDouble(stack.pop());
                double num2 = Double.parseDouble(stack.pop());
                double result = 0;
                switch (item) {
                    case "+": result = num1 + num2; break;
                    case "-": result = num2 - num1; break;
                    case "*": result = num1 * num2; break;
                    case "/": result = num2 / num1; break;
                    default:
                        System.out.println("运算符错误");
                }
                stack.push((int) result + "");
            }
        }
        return stack.peek();
    }


    // 比较运算符优先级
    public static int priority(String operator) throws Exception {
        if(operator.equals("+") || operator.equals("-")) {
            return 1;
        }else if(operator.equals("*") || operator.equals("/")) {
            return 2;
        }else {
            System.out.println("不存在该运算符");
        }
        return 0;
    }
}

解题思路

首先第一步,肯定要将一个数字和运算符的所有组合给排列出来,然后根据式子去计算结果,在和原来的数据进行比较即可,这里用到了关于表达式的算法问题,前缀表达式,后缀表达式(逆波兰表达式),中缀表达式,顺带复习一下

首先我们得到的式子肯定是中缀表达式,但中缀表达式不利于计算进行计算,所有需要将中缀表达式转为后缀表达式,转的步骤为:

1.初始化两个栈,运算符栈s1和存储中间结果栈s2
2.从左到右扫描中缀表达式
3.遇到操作数时,将操作数压入到s2
4.遇到运算符时,比较其与栈顶运算符的优先级:
   1.如果s1为空,或者栈顶运算符为“(”,则直接压入
   2.否则,若优先级比栈顶运算符高,也将运算符压入s1
   3.否则,优先级比栈顶运算符低,s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符比较
5.遇到括号时:
   1.如果是左括号,直接压入s1
   2.如果是右括号,则一次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
6.重复步骤2-5,直到表达式最右边
7.将s1中剩余的运算符依次弹出并压入s2
8.依次弹出s2中的元素并输出,结果的*逆序*即为中缀表达式对应的后缀表达式
 _括号并不算运算符_ 

这里不考虑括号的情况,所以代码会简单一些

其次将得到的后缀表达式进行算数运算,运算步骤为:

从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数
用运算符对他们做相应的计算,用后面的数对前面的数进行运算,
并将结果入栈,重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果

这里顺带提一下关于前缀表达式的计算步骤

1.从右至左进行扫描,将数字6543压入堆栈
2.遇到+运算符时,弹出栈中元素3和4,计算3+4的值得7,在将7压入栈
3.遇到*运算符时,弹出5和7,计算得35压入栈
4.最后-运算符,计算35-6的值,得出最终结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少睡点觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值