# 阿里春招实习3.15号编程题

## 第一题:我没在规定时间做出来。不知道下面的是不是对的
package Alibaba;

/**
 * 给定三个数字(a, b, c)
 * 每次取反 a或者b中一个的  某一个二进制位
 * 使的 a|b = c
 * 问最少几次

案例给的是:
(2,6,5)  反转3
(1,2,3)  反转0
 */

public class Demo1 {
    public static void main(String[] args) {
        int num = getNum(1,2,3);
        System.out.println(num);
    }



    public static int getNum(int a, int b, int c) {
        int count = 0;
        int[] arr = getindex(a | b, c);
        // 根据二进制位的不同进行操作
        // 如果是 a.b 的两个二进制位 都是1  或操作也是 1 但是与 c的哪一位(0)相反就必须 两个都改变
        // 其他情况只需要改变一个
        for (int i : arr) {
            if(i != -1){
                // 表示已经不需要反转的位置
                int temp = (a >> i) & 1;
                int temp2 = (b >> i) & 1;
                // 因为做的是或运算
                if(temp == 1 && temp2 == 1){
                    count += 2;
                }
                else {
                    count += 1;
                }

            }
        }
        return count;
    }

    /**
     * // 获取是那些 二进制位是不同的
     * 从右到左获取2进制中与是1的值的索引位置。但是是反的。是从最右边开始的
     * @param a
     * @param b
     * @return */
    public static int[] getindex(int a, int b){
        int c = a ^ b;
        int[] arr = new int[32];
        int k = 0;

        for (int i = 0; i < 32; i++) {
            k = c & 1;
            if(k == 1){
                arr[i] = i;
                c >>= 1;
            }else {
                arr[i] = -1;
            }
        }
        return arr;
    }
}

## 第二题,我个人认为我是对的,但是调试代码的时候总是认为我是错的
对啦。就是说的是输入输出,我也没看明白意思。而且说的是double保留四位小数。
可能我的double都是以为小数吧。
但是我记忆中的保留四位小数,不都是emmmmm格式化输出的时候吗?
请各位大佬指正
package Alibaba;


/**
 * 燃烧速度是1min/m
 * 1根n米的蜡烛分成两段
 * 分辨点燃, 一段烧完之后,另一段还剩余的 长度 >= 2 则继续拆分。直到烧完
 * 问燃烧时间的期望

案例给的是:
n = 4的时候 燃烧时间期望是2min
 */
public class Demo2 {
    public static void main(String[] args) {

        double x = average(5);
        System.out.println(x);

    }

    // 我的思路就行进行拆分
    // 比如5m的蜡烛
    // 拆分为(1,4),(2,3),(3,2),(4,1)分别进行燃烧
    // 他们的燃烧时间就是 min(1,4) +  average(abs(i - (n - i)))
    public static double average(int n){
        if(n <= 0){
            return 0;
        }
        if(n == 1){
            return 1d;
        }
        if(n == 2){
            return 1d;
        }
        double avage = 0d;
        int a = 10;
        int deta = 0;
        for(int i = 1; i < n; i++){
            deta = Math.abs(i - (n - i));
            avage = avage + Math.min(i, n - i) + average(deta);
        }

        return avage / (n - 1);
    }
}



#阿里巴巴##实习##Java工程师##面经#
全部评论
看看我的代码吧,应该是对的,主要是考的是位运算。
1 回复 分享
发布于 2021-03-15 23:54
第二题是只能切两次,不能无限切
点赞 回复 分享
发布于 2021-03-15 20:39
第一题想到个方法,用纯真值表和位运算做,考虑单个位置: a=1,b=1        c=0需要两次     c=1不需要 a=0,b=1        c=0需要一次     c=1不需要         (同a=1,b=0) a=0,b=0        c=0不需要        c=1需要一次 因为位运算没有2,所以拆成两个数计算次数 举例d=(a^c)&(b^c) a=1,b=1        c=0,d=1     c=1,d=0 a=0,b=1        c=0,d=0     c=1,d=0         (同a=1,b=0) a=0,b=0        c=0,d=0     c=1,d=1 e同理, a=1,b=1        c=0,e=1     c=1,e=0 a=0,b=1        c=0,e=1     c=1,e=0         (同a=1,b=0) a=0,b=0        c=0,e=0     c=1,e=0 不要觉得d、e奇怪,使用ac、bc真值表凑的     public Integer cal(Integer a,Integer b,Integer c) {         int ab = a|b,counter=0,                 d=(a^c)&(b^c),lastD,                 e=(ab)^c&(ab),lastE;         while(d!=0){             lastD = d % 2;             if(lastD==1)                 counter++;             d = d >> 1;         }         while(e!=0){             lastE = e % 2;             if(lastE==1)                 counter++;             e = e >> 1;         }         return counter;     } 没验证过其他的,可以帮我测一下
点赞 回复 分享
发布于 2021-03-16 03:14

相关推荐

10-11 17:45
门头沟学院 Java
走吗:别怕 我以前也是这么认为 虽然一面就挂 但是颇有收获!
点赞 评论 收藏
分享
评论
点赞
9
分享
牛客网
牛客企业服务