题目描述
给出两个仅包含“+”、“-”两种字符且长度相同字符串 s1、s2,你需要通过填充数字将这两个字符串恢复成一个合法的表达式。并且只能填入正整数,恢复后的表达式的值必须非负。
例如对于字符串“±”,你可以将其变成“1+1-2”,但是不可以变成“1+1-3”,也不可以变成“1+0-1”。定义你的消耗为你填充的所有正整数的和。比如“1+1-2”的消耗为 1 + 1 + 2 = 4。你需要将这两个字符串都恢复成合法表达式,并且尽量的使它们的差值最小,于此同时你还需要使你的消耗最小。
相信你通过思考已经发现最小差值总是 0,因此你只需要求出差值为 0 时的最小消耗即可。字符串长度都小于 100000。
输入两个字符串 s1 和 s2。
输出一个数字,表示最小消耗。
示例 1
输入:
“+±”
“–+”
输出:
10
注意
样例最优解为“1+1+1-1”,“3-1-1+1”。
解题方法:
首先可以确定最小值一定为 0。分两种情况讨论。
- 两个字符串都没有负号的时候,最优解的所有位置都填 1。最小消耗为 2*(n+1)。
- 表达式中仅需要有一个负号,表达式的值就可以为任何值。此时两个表达式可以相互调整,因此最小差也是 0。
表达式中除了第一位以外每位数字填 1 可以得到最小消耗,因为值加在哪一位都是等效的。
不妨假设都加在第一位。计算出 s1,s2 的正负号数量的差,分别为 x 和 y。假设第一位分别为 pa,pb,我们只需要使(pa+x==pb+y)即可。
假设最终表达式的值为 final,则 final=max(max(x, y) + 1, 0),则 pa=final-x,pb=final-y。
/**
* 恢复字符串
* @param s1
* @param s2
* @return
*/
public static int solution(String s1, String s2) {
int len1 = s1.length();
int len2 = s2.length();
//s1 + 的个数
int s1_1 = s1.length()-s1.replace("+","").length();
int s1_0 = len1 - s1_1;
//s2 + 的个数
int s2_1 = s2.length()-s2.replace("+","").length();
int s2_0 = len2 - s2_1;
int sub1 = s1_1 - s1_0 ;
int sub2 = s2_1 - s2_0 ;
int ret = 0;
if(sub1< 0 && sub2 < 0){
ret = len1 + len2 + Math.min(Math.abs(sub1),Math.abs(sub2)) * 2 + Math.abs(sub1 - sub2);
}else {
ret = len1 + len2 + 2 + Math.abs(sub1 - sub2);
}
return ret;
}