阿里笔试:对于一个01字符串,每次只能任意交换两个元素,或者把0变成1,或者把1变成0,或者反转整个字符串。那么从A串变成B串至少需要多少步。

题目:对于一个01字符串,每次只能任意交换两个元素,或者把0变成1,或者把1变成0,或者反转整个字符串。那么从A串变成B串至少需要多少步。

例子,1111000变成0010011至少需要3步。


思路1:首先可以分成两种情况,一种是反转,一种是不翻转。那么如何决定到底反转不翻转?可以比较不翻转时相同的位数,和翻转之后相同的位数,如果不翻转之前相同的位数多,那么反转显然是划不来的,如果反转之后相同的位数多,那么自然要选择反转。(反转可以使用StringBuilder的reverse)。然后比较上一次操作之后(反转或者不翻转),A是1,B是0的个数;A是0,B是1的个数。选择较小值,因为我们要进行这么多次的反转操作,剩下的就是变换操作。

还是上面的例子,不翻转相同的位数为2,翻转之后相同的位数为4,因此选择反转。

翻转之后:A:0 0 0 1 1 1 1

                 B:0 0 1 0 0 1 1

可以发现,翻转之后,A是1,B是0的个数为2,A是0,B是1的个数为1。因此我们需要的最小操作数为2,即一次反转加一次变换。

代码是copy别的人,因为这种方法虽然好理解,但是实现比较繁琐,我就没写了:


private static int help(String a, String b) {
        int res = 0;
        int n = a.length();
        //不反转相同的个数
        int counta = 0;
        int countb = 0;
        for (int i = 0 ; i < n ; i++){
            if (a.charAt(i) == b.charAt(i)) counta++;
            if (a.charAt(i) == b.charAt(n-i-1)) countb++;
        }
        if (countb > counta) {
            res++;
            b = reverse(b);
        }

        //翻转完之后看能不能交换
        //0001111
        //0010011
        StringBuilder s = new StringBuilder();
        StringBuilder p = new StringBuilder();

        for (int i = 0; i < n; i++) {
            if (a.charAt(i) != b.charAt(i)){
                s.append(a.charAt(i));
                p.append(b.charAt(i));
            }
        }
        //01100
        //10011
        int c = 0 , d = 0;
        for (char l : s.toString().toCharArray()){
            if (l == '1') c++;
            else d++;
        }
        res += Math.min(c , d);
        res += s.length() - 2 * (Math.min(c , d));

        return res;


    }

  

思路2:更为简单的方法,分别计算不翻转时,A为0,B为1的位数a,A为1,B为0的位数b,以及翻转之后A为0,B为1的位数c,A为1,B为0的位数d。最后的结果其实就是min(max(a,b),max(c,d)+1)。举个例子:max(a,b)=a,这意味着只要进行b次的交换,和a-b次的变换即可。反转之后一样的,但是需要加上反转的1。

public static int process(String stra,String strb){
		int a=0,b=0,c=0,d=0;
		for(int i=0;i<stra.length();i++){
			
		if((stra.charAt(i)!=strb.charAt(i))&&(stra.charAt(i)=='1')) 
				a++;		
		if(stra.charAt(i)!=strb.charAt(i)&&stra.charAt(i)=='0') 
				b++;
		if(stra.charAt(stra.length()-1-i)!=strb.charAt(i)&&stra.charAt(i)=='1') 
				c++;
		if(stra.charAt(stra.length()-1-i)!=strb.charAt(i)&&stra.charAt(i)=='0') 
				d++;	
		}
		
		return Math.min(Math.max(a,b), Math.max(c,d)+1);
	}

相对来说这种方法就简单多了。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值