阿里笔试4月1日,第一题暴力破解,求高效解答

题目:第一行输入整数T, 接下来每行输入一个只有0和1组成的二进制字符串,共输入T个字符串。对于每个字符串,可以翻转每个二进制位若干次,如果能够通过翻转变成全0字符串,输出最少翻转次数,否则输出“NO”;
翻转规则:0变成1,1变成0;翻转第i位时将相邻i-1,i+1的位置字符也翻转(i-1,i+1不能越界)
如:011: 翻转第3位变成000,故输出“1”;
01:输出“NO”
import java.util.*;
public class MyTest{
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        int T=Integer.valueOf(scanner.nextLine());
        //存放输入的二进制字符串
        List<String>input=new ArrayList<>();
        //存放结果字符串
        List<String>res=new ArrayList<>();
        while(T>0 && scanner.hasNextLine()){
            input.add(scanner.nextLine());
            //初始化为全NO
            res.add("NO");
            T--;
        }
        for(int i=0;i<input.size();i++){
            String temp=input.get(i);
            int len=temp.length();
            //全0就不用翻
            if(checkAllZeros(temp)){
                res.set(i,"0");continue;
            }
            //记录最小翻转次数
            int min_cnt=Integer.MAX_VALUE;
            //直接产生一个位翻转序列,(0表示对应的位不翻,1表示翻)0...01开始到1...11结束
            //总共有2^len种位翻转序列
            char[]zeros=new char[len];
            Arrays.fill(zeros,'0');
            //二进制字符串前缀0填充至len长度
            String prefixZeros=new String(zeros);
            //位翻转序列通过j转化为对应的二进制字符串来表示
            for(int j=1;j<=Math.pow(2,temp.length())-1;j++){
                StringBuilder sb=new StringBuilder(temp);
                String sequence=generateSequence(j,len,prefixZeros);
                int cnt=0;
                for(int p=0;p<len;p++){
                    if(sequence.charAt(p)=='1'){
                        sb=convert(sb,p);
                        cnt++;
                    }
                }
                //判断是否满足全0
                if(checkAllZeros(sb.toString())){
                    min_cnt=Math.min(min_cnt,cnt);
                }
            }
            if(min_cnt!=Integer.MAX_VALUE){
                res.set(i,String.valueOf(min_cnt));
            }
        }
        for(int i=0;i<res.size();i++){
            System.out.println(res.get(i));
        }
    }
    public static String generateSequence(int j,int len,String allZeros){
        //将j转换为二进制字符串,长度为len
        String s= allZeros+Integer.toBinaryString(j);
        return s.substring(s.length()-len,s.length());
    }
    public static StringBuilder convert(StringBuilder sb,int index){
        sb.setCharAt(index,getReverse(sb.charAt(index)));
        if(index>0){
            sb.setCharAt(index-1,getReverse(sb.charAt(index-1)));
        }
        if(index<sb.length()-1){
            sb.setCharAt(index+1,getReverse(sb.charAt(index+1)));
        }
        return sb;
    }
    public static char getReverse(char c){
        if(c=='0')return '1';
        else return '0';
    }
    public static boolean checkAllZeros(String s){
        for(int i=0;i<s.length();i++)
            if(s.charAt(i)=='1')return false;
        return true;
    }

}
输出测试:
10->'NO'
110-->'1'
101011-->“3” (3-->110111;1-->000111; 5-->000000)
...
#阿里笔试##笔试题目##阿里巴巴#
全部评论
帮你顶上去,同求解
点赞 回复 分享
发布于 2020-04-03 13:31
不知道题目有没有理解错。我的想法是:从左往右开始扫,每次让最左边的数字必须变成 0. 比如 1000110 这个 input,我们从第一位开始看,第一位是 1,那么第 1,2,3 位同时翻转,得到 0110110。然后看第二位,因为我们翻转过 1,2,3。所以第二位此时也是 1,我们翻转2,3,4 位,得到 0001110。然后第三位是 0 了,不翻转。然后第四位是 1,翻转 4,5,6,得到 0000000. 基本按照这个逻辑应该可以解出来
点赞 回复 分享
发布于 2020-04-03 13:42

相关推荐

09-27 00:29
东北大学 Java
伟大的麻辣烫:查看图片
阿里巴巴稳定性 77人发布 投递阿里巴巴等公司10个岗位
点赞 评论 收藏
分享
头像
11-09 12:17
清华大学 C++
out11Man:小丑罢了,不用理会
点赞 评论 收藏
分享
2 7 评论
分享
牛客网
牛客企业服务