一元一次方程的解
1、题目描述
输入一个仅由整数、某个小写字母以及{'+','-','=' }三种数学符号组成的一元一次方程,方程中的小写字母代表未知数,并且:
(1)因为这是一元一次方程,所以只有一种字母会出现在方程中;
(2) 所有方程中出现的所有整数都小于100000。
(3)请注意,减号字符'-'也可以作为负号使用。
(4)请注意,当结果为0时应避免答案具有负号。形如x=-0.000的答案不可得分。
题目保证输入的所有一元一次方程均是一个合法的方程且有唯一实数解,例如下面3个一元一次方程都是合法的:
a+1=2
2x-4=x+8
-7+z=10086
输入描述
输入一行字符串,即题目所述的一元一次方程。字符串长度小于100。
输出描述
输出一个字母,字符'='和一个保留到小数点后三位的小数,表示一元一次方程的解。
样例输入:
a+1=2a-9
样例输出:
a=10.000
2、解题思路
我们可以将方程看作:
左边表达式 = 右边表达式
将未知数的系数移到等号左边,常数项移到等号右边
最后解出
x = (常数和) / (系数和)
具体步骤:
将方程按
=
拆成左右两部分。分别解析左右表达式,统计未知数的系数和常数项。
解析时,遍历每个项(数字或字母或数字+字母),判断是系数还是常数。
移项后,左边系数 = 左边未知数系数 - 右边未知数系数,右边常数 = 右边常数 - 左边常数。
解
x = 常数 / 系数
。
方程表达式
我们可以用一个函数 parse
来处理一个表达式(如 "a+1"
),返回 (系数, 常数)
。
解析时:
用
+
或-
分割项(注意保留符号)如果项中包含字母,则是未知数项,系数 = 该项去掉字母后的数值(如果只有字母,系数为 1 或 -1)
如果不包含字母,则是常数项
边界情况
开头可能是负号,如
-x+1=0
系数为 1 或 -1 时省略数字
整数可能为 0
最终结果要避免
-0.000
3、时间复杂度
我们只需一次遍历解析两边表达式,所以是 O(n),n 为方程长度。
4、代码实现
import java.util.Scanner;public class Main {public static void main(String[] args) {//一元一次方程:将未知数的系数移到左边,常数项移到右边,通过x=(常数和)/(系数和)//分割方程式为左右//解析左右方程,获取系数和常数//移项//注意:避免-0.00Scanner in = new Scanner(System.in);String equation = in.nextLine();//找出未知数字母char variable = 'x';for (int i = 0; i < equation.length(); i++) {char ch = equation.charAt(i);if(ch>='a' && ch<='z'){variable = ch;break;}}//将方程式根据=分割成左右String[] sides = equation.split("=");String left = sides[0];String right = sides[1];//解析左右方程,获取系数和常数double[] leftRes = parseExpression(left,variable);double[] rightRes = parseExpression(right,variable);double coeL = leftRes[0];double conL = leftRes[1];double coeR = rightRes[0];double conR = rightRes[1];//移项后, 左边系数 = 左边未知数系数 - 右边未知数系数,右边常数 = 右边常数 - 左边常数double coeTotal = coeL - coeR;double conTotal = conR - conL;double x = conTotal / coeTotal;//注意:避免-0.00if(Math.abs(x) < 1e-10){x = 0.0;}System.out.printf("%c=%.3f\n",variable, x);}//parseExpression()用于处理表达式,返回系数,常数//通过+ 或者 - 分割项(需要保留符号)//如果像中包含字母,就是未知项//不会包含字母就是常数项private static double[] parseExpression(String expr, char var) {double coefficient = 0.0; //系数double constant = 0.0; //常数expr = "+" + expr; int i =0;while (i<expr.length()){int sign = 1;if(expr.charAt(i) == '+'){sign = 1;i++;} else if (expr.charAt(i) == '-') {sign = -1;i++;}//读取数字int j = i;while (j<expr.length() && (Character.isDigit(expr.charAt(j)) || expr.charAt(j) == '.')){j++;}String numStr = expr.substring(i,j);double num = 0.0;boolean hasDigit = !numStr.isEmpty();if(hasDigit){num = Double.parseDouble(numStr);}//检查变量if(j < expr.length() && expr.charAt(j) == var){if (!hasDigit){num = 1.0;}coefficient += sign * num;j++;}else {if (!hasDigit){num=0.0;}constant += sign * num;}i = j;}return new double[]{coefficient, constant};}
}