leetcode 640. Solve the Equation

257 篇文章 17 订阅

Solve a given equation and return the value of x in the form of string "x=#value". The equation contains only '+', '-' operation, the variable x and its coefficient(系数).

If there is no solution for the equation, return "No solution".

If there are infinite solutions for the equation, return "Infinite solutions".

If there is exactly one solution for the equation, we ensure that the value of x is an integer.

Example 1:

Input: "x+5-3+x=6+x-2"
Output: "x=2"

Example 2:

Input: "x=x"
Output: "Infinite solutions"

Example 3:

Input: "2x=x"
Output: "x=0"

Example 4:

Input: "2x+3x-6x=x+2"
Output: "x=-1"

Example 5:

Input: "x=x+2"
Output: "No solution"
这道题主要的是考察字符串的解析能力。
public String solveEquation(String equation) {
	String[] leftAndRight=equation.split("=");
	int[] left=solve(leftAndRight[0]);
	int[] right=solve(leftAndRight[1]);
	int x_xishu=left[0]-right[0];
	int changshu=right[1]-left[1];
	if(x_xishu==0&&changshu!=0){
		return "No solution";
	}
	if(x_xishu==0&&changshu==0){
		return "Infinite solutions";
	}
	int num=changshu/x_xishu;
	return "x="+num;
}

//int[0]返回当前表达式中x的系数
//int[1]返回当前表达式中的常数大小
public int[] solve(String s){
	int x_xishu=0;
	int changshu=0;
	int begin=0;
	int end=1;	
	char fuhao='+';
	if(s.charAt(0)=='-'){
		fuhao='-';
		begin=1;
		end=2;
	}	
	while (end <= s.length()) {
		while (end < s.length() && s.charAt(end) != '+' && s.charAt(end) != '-') {
			end++;
		}
		String the=s.substring(begin,end);
		if(the.indexOf('x')!=-1){//是系数
			String numString=the.substring(0, the.indexOf('x'));
			int num=1;
			if(!numString.equals("")){
				num=Integer.parseInt(numString);
			}
			if(fuhao=='+'){
				x_xishu+=num;
			}
			else{
				x_xishu-=num;
			}
		}
		else{//是常数
			int num=Integer.parseInt(the);
			if(fuhao=='+'){
				changshu+=num;
			}
			else{
				changshu-=num;
			}
		}			
		if(end<s.length()){
			fuhao = s.charAt(end);
		}			
		begin=end+1;
		end=begin+1;
	}
	return new int[]{x_xishu,changshu};
}
还有大神巧妙地运用了regrex中的奇淫技巧。

比如:x +5 -2x = 6 -3x; 那么运用了 rex 之后,
左边的表达式 : tokens= { x, +5, -2x };  x的系数 = 1-2 =-1; 常数 = 5;
右边的表达式: tokens= { 6, -3x };  x的系数 = -3; 常数 = 6;

public String solveEquation(String equation) {
    int[] res = evaluateExpression(equation.split("=")[0]),  
  	  res2 = evaluateExpression(equation.split("=")[1]);
    res[0] -= res2[0];
    res[1] = res2[1] - res[1];
    if (res[0] == 0 && res[1] == 0) return "Infinite solutions";
    if (res[0] == 0) return "No solution";
    return "x=" + res[1]/res[0];
}  

public int[] evaluateExpression(String exp) {
    String[] tokens = exp.split("(?=[-+])"); 
    int[] res =  new int[2];
    for (String token : tokens) {
        if (token.equals("+x") || token.equals("x")) res[0] += 1;
	else if (token.equals("-x")) res[0] -= 1;
	else if (token.contains("x")) res[0] += Integer.parseInt(token.substring(0, token.indexOf("x")));
	else res[1] += Integer.parseInt(token);
    }
    return res;
}

为啥 exp.split("(?=[-+])"); 得到的是包含+/-的token呢?可以看看stackoverflow的解答:https://stackoverflow.com/questions/10804732/what-is-the-difference-between-and-in-regex

I searched for the meaning of these expressions but couldn't understand the exact differnce between them. This is what they say:

  • ?: Match expression but do not capture it.
  • ?= Match a suffix but exclude it from capture.
  • ?! Match if suffix is absent.

I tried using these in simple RegEx and got similar results for all. example: the following 3 expressions give very similar results.

  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?!\.[a-zA-Z0-9]+)*
  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?=\.[a-zA-Z0-9]+)*
  • [a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9]+)*
share improve this question
 
 
Please show us your test case. They should not give the same results. –  Bergi  May 29 '12 at 18:41 
 
@sepp2k, it same similar results in few case, one of them mentioned in the question. –  RK Poddar  May 29 '12 at 18:41
 
@Bergi, i tested it with random data, containing english words, phone numbers, urls, e-mail addresses, numbers, etc.. –  RK Poddar  May 29 '12 at 18:43
4  
@RKAgarwal Ah, I see what you did there. You added a * after the groups, so they're simply ignored. –  sepp2k  May 29 '12 at 18:44
 
noobie note: you'd only use these at the start of parenthesis, and parenthesis form a capturing group (different parenthesis sets extract different sections of text). –  Ryan Taylor  Jun 7 at 19:06 

4 Answers

up vote 62 down vote accepted

The difference between ?= and ?! is that the former requires the given expression to match and the latter requires it to not match. For example a(?=b) will match the "a" in "ab", but not the "a" in "ac". Whereas a(?!b) will match the "a" in "ac", but not the "a" in "ab".

The difference between ?: and ?= is that ?= excludes the expression from the entire match while ?: just doesn't create a capturing group. So for example a(?:b) will match the "ab" in "abc", while a(?=b) will only match the "a" in "abc". a(b) would match the "ab" in "abc" and create a capture containing the "b".

share improve this answer
 
 
?:  is for non capturing group
?=  is for positive look ahead
?!  is for negative look ahead
?<= is for positive look behind
?<! is for negative look behind

Please check here: http://www.regular-expressions.info/lookaround.html for very good tutorial and examples on lookahead in regular expressions.

share improve this answer
 
12  
Yet JavaScript does not know lookbehind. –  Bergi  May 29 '12 at 18:45

Try matching foobar against these:

/foo(?=b)(.*)/
/foo(?!b)(.*)/

The first regex will match and will return "bar" as first submatch — (?=b) matches the 'b', but does not consume it, leaving it for the following parentheses.

The second regex will NOT match, because it expects "foo" to be followed by something different from "bar".

share improve this answer
 


这道题有solutions:https://leetcode.com/problems/solve-the-equation/solution/ (表示不太想看T_T)

Solution


Approach #1 Partioning Coefficients [Accepted]

In the current approach, we start by splitting the given equationequation based on = sign. This way, we've separated the left and right hand side of this equation. Once this is done, we need to extract the individual elements(i.e. x's and the numbers) from both sides of the equation. To do so, we make use of breakItfunction, in which we traverse over the given equation(either left hand side or right hand side), and put the separated parts into an array.

Now, the idea is as follows. We treat the given equation as if we're bringing all the x's on the left hand side and all the rest of the numbers on the right hand side as done below for an example.

x+5-3+x=6+x-2

x+x-x=6-2-5+3

Thus, every x in the left hand side of the given equation is treated as positive, while that on the right hand side is treated as negative, in the current implementation.

Likewise, every number on the left hand side is treated as negative, while that on the right hand side is treated as positive. Thus, by doing so, we obtain all the x's in the new lhslhs and all the numbers in the new rhsrhs of the original equation.

Further, in case of an x, we also need to find its corresponding coefficients in order to evaluate the final effective coefficient of x on the left hand side. We also evaluate the final effective number on the right hand side as well.

Now, in case of a unique solution, the ratio of the effective rhsrhs and lhslhs gives the required result. In case of infinite solutions, both the effective lhslhs and rhsrhsturns out to be zero e.g. x+1=x+1. In case of no solution, the coefficient of x(lhslhs) turns out to be zero, but the effective number on the rhsrhs is non-zero.

Java

public class Solution {
    public String coeff(String x) {
        if (x.length() > 1 && x.charAt(x.length() - 2) >= '0' && x.charAt(x.length() - 2) <= '9')
            return x.replace("x", "");
        return x.replace("x", "1");
    }
    public String solveEquation(String equation) {
        String[] lr = equation.split("=");
        int lhs = 0, rhs = 0;
        for (String x: breakIt(lr[0])) {
            if (x.indexOf("x") >= 0) {
                lhs += Integer.parseInt(coeff(x));
            } else
                rhs -= Integer.parseInt(x);
        }
        for (String x: breakIt(lr[1])) {
            if (x.indexOf("x") >= 0)
                lhs -= Integer.parseInt(coeff(x));
            else
                rhs += Integer.parseInt(x);
        }
        if (lhs == 0) {
            if (rhs == 0)
                return "Infinite solutions";
            else
                return "No solution";
        }
        return "x=" + rhs / lhs;
    }
    public List < String > breakIt(String s) {
        List < String > res = new ArrayList < > ();
        String r = "";
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '+' || s.charAt(i) == '-') {
                if (r.length() > 0)
                    res.add(r);
                r = "" + s.charAt(i);
            } else
                r += s.charAt(i);
        }
        res.add(r);
        return res;
    }
}

Complexity Analysis

  • Time complexity : O(n)O(n). Generating cofficients and findinn $lhsandandrhswill takewilltakeO(n)$$.

  • Space complexity : O(n)O(n). ArrayList resres size can grow upto nn.


Approach #2 Using regex for spliting [Accepted]

Algorithm

In the last approach, we made use of a new function breakIt to obtain the individual components of either the left hand side or the right hand side. Instead of doing so, we can also make use of splitting based on + or - sign, to obtain the individual elements. The rest of the process remains the same as in the last approach.

In order to do the splitting, we make use of an expression derived from regular expressions(regex). Simply speaking, regex is a functionality used to match a target string based on some given criteria. The ?=n quantifier, in regex, matches any string that is followed by a specific string nn. What it's saying is that the captured match must be followed by nn but the nn itself isn't captured.

By making use of this kind of expression in the split functionality, we make sure that the partitions are obtained such that the + or - sign remains along with the parts(numbers or coefficients) even after the splitting.

Java

public class Solution {
    public String coeff(String x) {
        if (x.length() > 1 && x.charAt(x.length() - 2) >= '0' && x.charAt(x.length() - 2) <= '9')
            return x.replace("x", "");
        return x.replace("x", "1");
    }
    public String solveEquation(String equation) {
        String[] lr = equation.split("=");
        int lhs = 0, rhs = 0;
        for (String x: lr[0].split("(?=\\+)|(?=-)")) {
            if (x.indexOf("x") >= 0) {

                lhs += Integer.parseInt(coeff(x));
            } else
                rhs -= Integer.parseInt(x);
        }
        for (String x: lr[1].split("(?=\\+)|(?=-)")) {
            if (x.indexOf("x") >= 0)
                lhs -= Integer.parseInt(coeff(x));
            else
                rhs += Integer.parseInt(x);
        }
        if (lhs == 0) {
            if (rhs == 0)
                return "Infinite solutions";
            else
                return "No solution";
        } else
            return "x=" + rhs / lhs;
    }
}

Complexity Analysis

  • Time complexity : O(n)O(n). Generating coefficients and finding $lhsandandrhswill takewilltakeO(n)$$.

  • Space complexity : O(n)O(n). ArrayList resres size can grow upto nn.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值