一、题目阐述
这是 codewars 上的一道题,等级 6。题目如下:
给定一个方程形式的字符串 s,任务是从 s 中算出 X 的值。
测试代码:
二、解题思路
首先可以粗略得到步骤:从字符串中得到数字,计算X。下面我们一步一步走。
2.1、提取数字
我使用了正则表达式的方法来提取这关键的三个数值。(注:我的正则可能写的比较粗糙,如有更好的,请忽略我的写法。)
import java.util.regex.*;
Pattern p = Pattern.compile("(\\d+)X=(\\d+).*?(\\d+).*");
Matcher m = p.matcher(s);
// 先用字符串类型得到数值用于后续强制转换
String s1 = "";
String s2 = "";
String s3 = "";
while(m.find() == true){
s1 = m.group(1);
s2 = m.group(2);
s3 = m.group(3);
}
2.2、计算 X
抽象方程式为: aX = b(mod c)
这个时候,我们分析这个方程的计算步骤大致如下:
1. 通过取余操作,简化 a、b
2. 若 (b + N*c)/a 存在,X 等于这个比值;否则,返回 X = -1 ( N 为任意非负整数)
显然第一步很好操作,代码如下:
int new_s1 = Integer.parseInt(s1) % Integer.parseInt(s3);
int new_s2 = Integer.parseInt(s2) % Integer.parseInt(s3);
int new_s3 = Integer.parseInt(s3);
关于第二步,对于 (b + N*c)/a,当 b 是 a 的倍数时,X 为 b/a;当 b 不是 a 的倍数,难点在于 N,在这里 N 最大取到 a(new_s1) 即可。理由如下:
当 N 足够大的时候,式子可以拆分为
这说明只要在小于 a 次循环中找到 a 的倍数 b + N1*c 即可。
然后写一个循环,代码如下
int result = -1;
for(int i = 0; i < new_s1;i++){
if(new_s2 % new_s1 == 0){
result = new_s2/new_s1;
break;
}
new_s2 += new_s3;
}
return result;
三、完整代码
import java.util.regex.*;
public class FindIt {
public int findIt(String s) {
Pattern p = Pattern.compile("(\\d+)X=(\\d+).*?(\\d+).*");
Matcher m = p.matcher(s);
String s1 = "";
String s2 = "";
String s3 = "";
while(m.find() == true){
s1 = m.group(1);
s2 = m.group(2);
s3 = m.group(3);
}
int new_s1 = Integer.parseInt(s1) % Integer.parseInt(s3);
int new_s2 = Integer.parseInt(s2) % Integer.parseInt(s3);
int new_s3 = Integer.parseInt(s3);
int result = -1;
for(int i = 0; i < new_s1;i++){
if(new_s2 % new_s1 == 0){
result = new_s2/new_s1;
break;
}
new_s2 += new_s3;
}
return result;
}
}