解单变量线性方程
Solving a linear equation in one variable
什么将是最有效的算法来解决线性方程在一个变量给定的字符串输入到一个函数?例如,对于输入字符串:
"x + 9 - 2 - 4 + x = - x + 5 - 1 + 3 - x"
输出应为1。
我正在考虑使用堆栈并在遇到字符串中的空格时将每个字符串标记压入其中。如果输入是波兰符号,那么从堆栈中弹出数字以获得结果会更容易,但我不确定这里采取什么方法。
这是一个面试问题。一旦你算出方程a * x + b = 0
中的系数a
和b
,解线性方程(我希望)对你来说非常容易。
所以,问题的困难部分是解析表达式并"评估"它以找到系数。您的示例表达式非常简单,它只使用一元-
,二进制-
,二进制+
操作符。还有=
,你可以特别处理。
从问题中不清楚解决方案是否也应该处理包含二进制*
和/
或括号的表达式。我想知道这个面试问题是不是有意的:
- 让你写一些简单的代码,或者
- 让你在写任何东西之前问一下问题的真正范围是什么。
都是很重要的技能:-)
这个问题甚至可能是有意的:
- 将那些有很多编写解析器经验的人(他们会尽可能快地解决问题)与那些没有编写解析器经验的人(他们可能会在几分钟内努力解决问题,至少没有一些提示)分开。
x
中的线性表达式值,并将=
解释为具有最低优先级的操作符,这意味着"减去"。结果是x
中的线性表达式等于0
。
如果你不需要复杂的表达式,那么你可以直接从左到右计算这个简单的例子,一旦你把它标记了[*]:
x
x + 9
// set the "we've found minus sign" bit to negate the first thing that follows
x + 7 // and clear the negative bit
x + 3
2 * x + 3
// set the "we've found the equals sign" bit to negate everything that follows
3 * x + 3
3 * x - 2
3 * x - 1
3 * x - 4
4 * x - 4
最后将a * x + b = 0
解为x = - b/a
。
[*]示例标记化代码,在Python中:
acc = None
for idx, ch in enumerate(input):
if ch in '1234567890':
if acc is None: acc = 0
acc = 10 * acc + int(ch)
continue
if acc != None:
yield acc
acc = None
if ch in '+-=x':
yield ch
elif ch == ' ':
pass
else:
raise ValueError('illegal character "%s" at %d' % (ch, idx))
另一个标记化示例代码,同样在Python中,假设标记之间总是有空格,如示例中所示。这就把令牌验证留给了解析器:
return input.split()
可以使用一些简单的伪代码来解决这个问题
function(stinrgToParse){
arrayoftokens = stringToParse.match(RegexMatching);
foreach(arrayoftokens as token)
{
//now step through the tokens and determine what they are
//and store the neccesary information.
}
//Use the above information to do the arithmetic.
//count the number of times a variable appears positive and negative
//do the arithmetic.
//add up the numbers both positive and negative.
//return the result.
}
第一件事是解析字符串,识别各种标记(数字、变量和操作符),以便通过给操作符适当的优先级来形成表达式树。
正则表达式可以提供帮助,但这不是唯一的方法(像boost::spirit这样的语法解析器也很好,你甚至可以运行自己的语法解析器:这都是"查找和追偿")。
然后可以通过减少执行那些处理常量的操作的节点,并通过将变量相关的操作分组,相应地执行这些操作来操纵树。
这将递归地继续下去,直到您保留与变量相关的节点和常量节点。
在这一点解被简单地计算。
它们基本上是导致产生解释器或编译器的相同原则。
考虑:
from operator import add, sub
def ab(expr):
a, b, op = 0, 0, add
for t in expr.split():
if t == '+': op = add
elif t == '-': op = sub
elif t == 'x': a = op(a, 1)
else : b = op(b, int(t))
return a, b
给定一个表达式,如1 + x - 2 - x...
,将其转换为规范形式ax+b
,并返回一对系数(a,b)
。
现在,让我们从方程的两个部分得到系数:
le, ri = equation.split('=')
a1, b1 = ab(le)
a2, b2 = ab(ri)
,最终解出平凡方程a1*x + b1 = a2*x + b2
:
x = (b2 - b1) / (a1 - a2)
当然,这只解决了这个特定的例子,没有操作符优先级或括号。要支持后者,您需要一个解析器,可能是递归下降解析器,手工编写会更简单。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- C++中高效的大型稀疏块压缩线性方程
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- 试图让变量检查数组中的某些内容
- Cpp-Tuple使用带有变量的get
- 将包含C样式数组的对象初始化为成员变量(C++)
- 当vector是tje全局变量时,c++中vector的内存管理
- 通过多个头文件使用常量变量
- 在 n 个变量中查找单个线性方程的解,或确定不存在解
- 解单变量线性方程