美团2020春招笔试题java代码

2 篇文章 0 订阅
1 篇文章 0 订阅

美团2020春招笔试题java代码


题目表述: 第一行输入数字个数,第二行输入一组数字(非负)。如果这组数字中的数字的二进制表示的相反数(即两个数字的二进制每一位都相反)存在于这组数字中,输出对应位置为-1,否则为1。
例如 :
输入
4
3 5 6 1
输出:1 1 -1 -1
6的二进制表示:110 , 1的二进制表示:001。 每一位都相反。
思路:将输入的数字和序号作为<key,value>存入hashMap中,计算每个数字的二进制相反数,如果map中存在,则结果数组该位置置为-1,否则为1。需要注意的是相反数不至只有一个,根据数字的二进制表示的位数不同
例如:1的二进制表示为:1,01,001,0001 则二进制相反数有:0,10,110,1110。虽然int类型有32位,但是不需要全部枚举, 只要相反数不大于数组中的最大值即可,所以计算出第一个相反数,高位补1,去map中查找即可。相反数大于最大值则停止搜索。
代码如下:

public static void main(String[] args) {
    Scanner sc=  new Scanner(System.in);
    int n = sc.nextInt();
    int[] ans = new int[n];
    HashMap<Integer,Integer> map  = new HashMap<>();
    int max = -1;
    for(int i = 0;i<n;i++){
        int v =sc.nextInt();
        if(v>max) max = v; //记录最大值
        map.put(v,i);
    }

    for(Integer key:map.keySet())
    {
        if(getRevers(key,max,map)){ ans[map.get(key)]=-1;}//相反数存在
        else{ ans[map.get(key)]=1;}
    }
    System.out.println(Arrays.toString(ans));
}

private static boolean getRevers(int key,int max,HashMap<Integer,Integer> map ) {
  int revs; int len;
    String s  = Integer.toBinaryString(max);//将十进制转化为二进制
    len = s.length();//记录最大值二进制表示长度
     s  = Integer.toBinaryString(key);//将key十进制转化为二进制
    StringBuilder strBuilder = new StringBuilder(s);
    for(int i=0; i<s.length();i++){
        int a = (int)s.charAt(i)^1;
        strBuilder.setCharAt(i, (char)a); //二进制取反
    }
    s = strBuilder.toString();
    len = len-s.length();
    revs = Integer.parseInt(s,2);
    if(map.containsKey(revs)) return true;

    while(len-->0){ //相反数二进制长度 < max的二进制长度
        s = "1"+s;
        revs = Integer.parseInt(s,2);
        if(map.containsKey(revs)) return true;
    }

  return false;
}

因为笔试时用数组,双循环按位与进行比较计算。通过率只有55%。原因出在时间复杂度超出限制,数字大小在0~10^6范围。所以循环比较容易超时。所以又思考了一下直接计算二进制相反数以及借助hashMap容器可以大幅度缩短比较时间。值得注意的是相反数的枚举(不唯一)和需要用最大值进行限制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值