面试Coding(一):反转long

1、前言

在经历一个月的面试后,笔者回到家休息,不曾想晚上10点多收到Base地广州某大厂第二天早上的面试,为了把握秋招的每次机会,笔者连夜回学校取回电脑,全力面对第二天的面试,不曾想面的稀碎!

(本文有水印的图片是笔者在自己其他博客网站拷过来附带的)

2、反转long

面试的三道coding中有一道反转long的题目,下面介绍下原题大概的内容:
给出一个无符号long类型数字,反转其64位比特位,并计算运行1000万次所需要的耗时。

public static void main(String[] args) {
    long num = 4;
    String numStr = Long.toBinaryString(num);
    String swapNumStr = Long.toBinaryString(swapLong(num));
    System.out.println(check(numStr, swapNumStr));
    long t1 = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        swapLong(num);
    }
    long t2 = System.currentTimeMillis();
    System.out.println(t2-t1);
}

public static boolean check(String source,String target){
    StringBuilder sb1 = new StringBuilder(source);
    StringBuilder sb2 = new StringBuilder(target);
    //补0
    while (sb1.length() < 64){
        sb1.insert(0,"0");
    }
    while (sb2.length() < 64){
        sb2.insert(0,"0");
    }
    System.out.println(sb1);
    System.out.println(sb2);
    return sb1.reverse().toString().equals(sb2.toString());
}


public static long swapLong(long val){
    long result = 0;
    int num = 1;
    //左移
    while (num <= 32){
        //为1的位置
        int index = 32 + num;
        long fix = 1;
        for (int i = 1; i < index; i++) {
            fix = fix << 1;
        }
        result += ((val << (1 + 2*(num-1))) & fix);
        num++;
    }
    //右移
    num = 1;
    while (num <= 32){
        //为1的位置
        int index = 33 - num;
        long fix = 1;
        for (int i = 1; i < index; i++) {
            fix = fix << 1;
        }
        result += ((val >>> (1 + 2*(num-1))) & fix);
        num++;
    }
    return result;
}

输出为


大概思路是将64位比特分为左右两半,找到右边比特位反转后的位置(算第一位为1,那么第30位反转后应该到第35位),计算出位置后,通过位操作得到一个fix(这个数从二进制角度来看只有一个位是1,其余是0,而1那个位正是反转后的位置)。然后只需要对val做位操作,使需要反转的比特位移到对应的位置,再通过位与运算,就可以得到该位上的值,然后相加,这样的操作重复64次(左边32次,右边32次),最后即可得到结果。

3、注意点

补零

计算完之后通过Long.toBinaryString换算成二进制字符串后,要记得补0,笔者就是面试的时候写出来了,换算成二进制字符串后发现不对劲,以为自己写错了

image.png


上面这副图就是不补零直接输出的效果,一眼看过去就以为自己写错了。可能有人问,为什么不是补1呢?有可能他反转后是个负数呢?
下面看一个数为327179121787189L的例子

image.png


可以看到,如果反转后最高位是1,那么其实他是不会被忽略掉的,前面的例子是因为最高几位是0,所以把最高几位都忽略掉了,才导致看起来出错的情况

计算fix

这里计算fix有人可能觉得使用Math.pow也可以,笔者面试时也是用这个函数,但是确出现了一些诡异的情况,在计算到第64位时,这个值会减1

long pow = (long) Math.pow(2, 63);//计算第64位为1的fix
System.out.println(pow);
System.out.println(Long.toBinaryString(pow));


正常来说应该是9223372036854775808,但是值却减了1,个人认为是因为long最大值就是9223372036854775807,所以java自动帮你调为了这个值(求2的67次方也是会得到这个值),因为该方法时native方法看不到其实现

4、总结

总的来说,在做这些现场coding最好所有方法都由自己实现,否则出现一些奇怪的bug,可能会扰乱自己的心态,在这里也祝大家(还有笔者)秋招都有offer

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值