恢复字符串--算法笔试模拟题精解

题目描述

给出两个仅包含“+”、“-”两种字符且长度相同字符串 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. 两个字符串都没有负号的时候,最优解的所有位置都填 1。最小消耗为 2*(n+1)。
  2. 表达式中仅需要有一个负号,表达式的值就可以为任何值。此时两个表达式可以相互调整,因此最小差也是 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;
    }

你可能感兴趣的:(算法)