Leetcode 640 求解方程
PS:这个是之前在牛客网上做了快手的算法笔试真题中有一道是解一元一次方程。一开始思路是尝试将字符串转化成列表然后暴力破解,但是多次尝试以后报错,因为方程移项问题导致整个过程非常繁琐容易出错。因此在查阅资料之后发现了eval函数的巧妙用法,具体思路可以参阅https://everet.org/linear-equations-solvers-in-python.html。
说回到这个题,和我之前做的那个解方程的题有很多相似的地方,但是里面的问题也变多了,总结起来有以下几点:
-
对结果的划分。题目要求输出结果要被分成三类:一类是‘No solution’, 一类是‘Infinite solutions’ ,和整数解。
-
对字符串的处理。在测试用例中会出现这样形式的字符串“2x=x”。注意这里省略了“*”会导致eval函数报错,因此要对字符串进行处理。
下面我们就来解决这两个问题:
对于第一个问题,其实是一个数学问题。只要我们能够理解好eval函数的输出值是一个复数,我们就可以对结果进行合理的分类。
r = eval(eq_new, {var:1j})
if r.imag == 0 and r.real != 0:
return 'No solution'
if r.imag ==0 and r.real == 0:
return 'Infinite solutions'
else:
return 'x=' + str(int(-r.real//r.imag))
我们根据复数的实部和虚部进行分类。当实部虚部都等于0的时候,我们有无穷多的解;当实部不等于0但虚部等于0的时候,结果是无解;其他情况可以直接返回结果(注意按题目要求返回的是一个字符串,解应该是一个整数)
第二个问题虽然还是比较麻烦,但是相对于直接暴力破解要简单的多。
先上代码:
equation = equation.replace('=', '-(')+')'
eq_lis = list(equation)
for i in range(len(eq_lis)):
if eq_lis[i].isdigit() and eq_lis[i+1] == 'x':
eq_lis[i] = eq_lis[i] + '*'
eq_new = ''.join(eq_lis)
首先,把原来的字符串处理成没有等式的形式。然后处理“2x”这样的非法字符。我采用的方法比较笨,先变成一个list然后判断如果是数字跟着x的形式,就直接把数字变成“数字+*”的形式,然后把list再组合起来,这样就得到了eval里合法的字符串。
完整代码:
class Solution:
def solveEquation(self, equation: str, var='x') -> str:
equation = equation.replace('=', '-(')+')'
eq_lis = list(equation)
for i in range(len(eq_lis)):
if eq_lis[i].isdigit() and eq_lis[i+1] == 'x':
eq_lis[i] = eq_lis[i] + '*'
eq_new = ''.join(eq_lis)
r = eval(eq_new, {var:1j})
if r.imag == 0 and r.real != 0:
return 'No solution'
if r.imag ==0 and r.real == 0:
return 'Infinite solutions'
else:
return 'x=' + str(int(-r.real//r.imag))
结果反馈:
由于用了eval函数,所以整个过程只在处理等式的时候开辟了O(n)的空间,相对于题解里其他答案使用空间更小。